diff options
author | Dave Airlie <airlied@redhat.com> | 2017-04-03 02:30:24 -0400 |
---|---|---|
committer | Dave Airlie <airlied@redhat.com> | 2017-04-03 02:30:24 -0400 |
commit | 320d8c3d38739fa8e31a076b86cbdafcf8897d5e (patch) | |
tree | ac43e4981ad56b9612cd0cfc0e075401da38f89f | |
parent | 7558ab66424e61819cbf3d778d9f780f3aa205e9 (diff) | |
parent | b121b051d14cc6e4e799e96e9c06c55989f9e073 (diff) |
Merge tag 'drm-misc-next-2017-03-31' of git://anongit.freedesktop.org/git/drm-misc into drm-next
drm-misc for 4.12:
Core:
- Removed some fb subsampling dimension checks from core (Ville)
- Some MST slot cleanup (Dhinakaran)
- Extracted drm_debugfs.h & drm_ioctl.h from drmP.h (Daniel)
- Added drm_atomic_helper_shutdown() to compliment suspend/resume counterparts
(Daniel)
- Pipe context through legacy modeset to remove legacy_backoff nasties (Daniel)
- Cleanups around vblank as well as allowing lockless counter reads (Chris W.)
- VGA Switcheroo added to MAINTAINERS with Lukas Wunner as reviewer (Lukas)
Drivers:
- Enhancements to rockchip driver probe (Jeffy) and dsi (Chris Z.)
- Thunderbolt external GPU awareness added (Lukas)
* tag 'drm-misc-next-2017-03-31' of git://anongit.freedesktop.org/git/drm-misc: (63 commits)
apple-gmux: Don't switch external DP port on 2011+ MacBook Pros
drm/nouveau: Don't register Thunderbolt eGPU with vga_switcheroo
drm/amdgpu: Don't register Thunderbolt eGPU with vga_switcheroo
drm/radeon: Don't register Thunderbolt eGPU with vga_switcheroo
PCI: Recognize Thunderbolt devices
MAINTAINERS: Add Lukas Wunner as reviewer for vga_switcheroo
drm: Fix locking gotcha in page_flip ioctl
drm: Clarify the role of plane_state argument to drm_simple update().
drm: Clear e after kfree in drm_mode_page_flip_ioctl
drm: Convert cmpxchg(bool) back to a two step operation
drm/bridge: ti-tfp410: support hpd via gpio
drm: use .hword to represent 16-bit numbers
Revert unrelated part of "drm: simplify the locking in the GETCRTC ioctl"
drm: Fixup failure paths in drm_atomic_helper_set_config
drm: Peek at the current counter/timestamp for vblank queries
drm: Refactor vblank sequence number comparison
drm: vblank cannot be enabled if dev->irq_enabled is false
drm: Mark up accesses of vblank->enabled outside of its spinlock
drm: Make the decision to keep vblank irq enabled earlier
drm/atomic-helper: Remove the backoff hack from set_config
...
101 files changed, 1596 insertions, 769 deletions
diff --git a/Documentation/EDID/edid.S b/Documentation/EDID/edid.S index 7ac03276d7a2..ef082dcc6084 100644 --- a/Documentation/EDID/edid.S +++ b/Documentation/EDID/edid.S | |||
@@ -59,9 +59,9 @@ | |||
59 | /* Fixed header pattern */ | 59 | /* Fixed header pattern */ |
60 | header: .byte 0x00,0xff,0xff,0xff,0xff,0xff,0xff,0x00 | 60 | header: .byte 0x00,0xff,0xff,0xff,0xff,0xff,0xff,0x00 |
61 | 61 | ||
62 | mfg_id: .word swap16(mfgname2id(MFG_LNX1, MFG_LNX2, MFG_LNX3)) | 62 | mfg_id: .hword swap16(mfgname2id(MFG_LNX1, MFG_LNX2, MFG_LNX3)) |
63 | 63 | ||
64 | prod_code: .word 0 | 64 | prod_code: .hword 0 |
65 | 65 | ||
66 | /* Serial number. 32 bits, little endian. */ | 66 | /* Serial number. 32 bits, little endian. */ |
67 | serial_number: .long SERIAL | 67 | serial_number: .long SERIAL |
@@ -177,7 +177,7 @@ std_vres: .byte (XY_RATIO<<6)+VFREQ-60 | |||
177 | 177 | ||
178 | descriptor1: | 178 | descriptor1: |
179 | /* Pixel clock in 10 kHz units. (0.-655.35 MHz, little-endian) */ | 179 | /* Pixel clock in 10 kHz units. (0.-655.35 MHz, little-endian) */ |
180 | clock: .word CLOCK/10 | 180 | clock: .hword CLOCK/10 |
181 | 181 | ||
182 | /* Horizontal active pixels 8 lsbits (0-4095) */ | 182 | /* Horizontal active pixels 8 lsbits (0-4095) */ |
183 | x_act_lsb: .byte XPIX&0xff | 183 | x_act_lsb: .byte XPIX&0xff |
diff --git a/Documentation/devicetree/bindings/display/rockchip/dw_mipi_dsi_rockchip.txt b/Documentation/devicetree/bindings/display/rockchip/dw_mipi_dsi_rockchip.txt index 188f6f7403e6..1d722f5055ab 100644 --- a/Documentation/devicetree/bindings/display/rockchip/dw_mipi_dsi_rockchip.txt +++ b/Documentation/devicetree/bindings/display/rockchip/dw_mipi_dsi_rockchip.txt | |||
@@ -10,7 +10,7 @@ Required properties: | |||
10 | - interrupts: Represent the controller's interrupt to the CPU(s). | 10 | - interrupts: Represent the controller's interrupt to the CPU(s). |
11 | - clocks, clock-names: Phandles to the controller's pll reference | 11 | - clocks, clock-names: Phandles to the controller's pll reference |
12 | clock(ref) and APB clock(pclk). For RK3399, a phy config clock | 12 | clock(ref) and APB clock(pclk). For RK3399, a phy config clock |
13 | (phy_cfg) is additional required. As described in [1]. | 13 | (phy_cfg) and a grf clock(grf) are required. As described in [1]. |
14 | - rockchip,grf: this soc should set GRF regs to mux vopl/vopb. | 14 | - rockchip,grf: this soc should set GRF regs to mux vopl/vopb. |
15 | - ports: contain a port node with endpoint definitions as defined in [2]. | 15 | - ports: contain a port node with endpoint definitions as defined in [2]. |
16 | For vopb,set the reg = <0> and set the reg = <1> for vopl. | 16 | For vopb,set the reg = <0> and set the reg = <1> for vopl. |
diff --git a/Documentation/gpu/drm-uapi.rst b/Documentation/gpu/drm-uapi.rst index 352652810dab..76356c86e358 100644 --- a/Documentation/gpu/drm-uapi.rst +++ b/Documentation/gpu/drm-uapi.rst | |||
@@ -207,6 +207,18 @@ Display CRC Support | |||
207 | .. kernel-doc:: drivers/gpu/drm/drm_debugfs_crc.c | 207 | .. kernel-doc:: drivers/gpu/drm/drm_debugfs_crc.c |
208 | :doc: CRC ABI | 208 | :doc: CRC ABI |
209 | 209 | ||
210 | .. kernel-doc:: drivers/gpu/drm/drm_debugfs_crc.c | ||
211 | :export: | ||
212 | |||
213 | Debugfs Support | ||
214 | --------------- | ||
215 | |||
216 | .. kernel-doc:: include/drm/drm_debugfs.h | ||
217 | :internal: | ||
218 | |||
219 | .. kernel-doc:: drivers/gpu/drm/drm_debugfs.c | ||
220 | :export: | ||
221 | |||
210 | VBlank event handling | 222 | VBlank event handling |
211 | ===================== | 223 | ===================== |
212 | 224 | ||
diff --git a/Documentation/gpu/introduction.rst b/Documentation/gpu/introduction.rst index 1f8bd5ef5f9d..05a82bdfbca4 100644 --- a/Documentation/gpu/introduction.rst +++ b/Documentation/gpu/introduction.rst | |||
@@ -60,3 +60,28 @@ checkpatch or sparse. We welcome such contributions. | |||
60 | 60 | ||
61 | Anyone looking to kick it up a notch can find a list of janitorial tasks on | 61 | Anyone looking to kick it up a notch can find a list of janitorial tasks on |
62 | the :ref:`TODO list <todo>`. | 62 | the :ref:`TODO list <todo>`. |
63 | |||
64 | Contribution Process | ||
65 | ==================== | ||
66 | |||
67 | Mostly the DRM subsystem works like any other kernel subsystem, see :ref:`the | ||
68 | main process guidelines and documentation <process_index>` for how things work. | ||
69 | Here we just document some of the specialities of the GPU subsystem. | ||
70 | |||
71 | Feature Merge Deadlines | ||
72 | ----------------------- | ||
73 | |||
74 | All feature work must be in the linux-next tree by the -rc6 release of the | ||
75 | current release cycle, otherwise they must be postponed and can't reach the next | ||
76 | merge window. All patches must have landed in the drm-next tree by latest -rc7, | ||
77 | but if your branch is not in linux-next then this must have happened by -rc6 | ||
78 | already. | ||
79 | |||
80 | After that point only bugfixes (like after the upstream merge window has closed | ||
81 | with the -rc1 release) are allowed. No new platform enabling or new drivers are | ||
82 | allowed. | ||
83 | |||
84 | This means that there's a blackout-period of about one month where feature work | ||
85 | can't be merged. The recommended way to deal with that is having a -next tree | ||
86 | that's always open, but making sure to not feed it into linux-next during the | ||
87 | blackout period. As an example, drm-misc works like that. | ||
diff --git a/Documentation/gpu/kms-properties.csv b/Documentation/gpu/kms-properties.csv index 981873a05d14..927b65e14219 100644 --- a/Documentation/gpu/kms-properties.csv +++ b/Documentation/gpu/kms-properties.csv | |||
@@ -1,10 +1,5 @@ | |||
1 | Owner Module/Drivers,Group,Property Name,Type,Property Values,Object attached,Description/Restrictions | 1 | Owner Module/Drivers,Group,Property Name,Type,Property Values,Object attached,Description/Restrictions |
2 | ,,“scaling mode”,ENUM,"{ ""None"", ""Full"", ""Center"", ""Full aspect"" }",Connector,"Supported by: amdgpu, gma500, i915, nouveau and radeon." | 2 | ,,“scaling mode”,ENUM,"{ ""None"", ""Full"", ""Center"", ""Full aspect"" }",Connector,"Supported by: amdgpu, gma500, i915, nouveau and radeon." |
3 | ,Connector,“EDID”,BLOB | IMMUTABLE,0,Connector,Contains id of edid blob ptr object. | ||
4 | ,,“DPMS”,ENUM,"{ “On”, “Standby”, “Suspend”, “Off” }",Connector,Contains DPMS operation mode value. | ||
5 | ,,“PATH”,BLOB | IMMUTABLE,0,Connector,Contains topology path to a connector. | ||
6 | ,,“TILE”,BLOB | IMMUTABLE,0,Connector,Contains tiling information for a connector. | ||
7 | ,,“CRTC_ID”,OBJECT,DRM_MODE_OBJECT_CRTC,Connector,CRTC that connector is attached to (atomic) | ||
8 | ,DVI-I,“subconnector”,ENUM,"{ “Unknown”, “DVI-D”, “DVI-A” }",Connector,TBD | 3 | ,DVI-I,“subconnector”,ENUM,"{ “Unknown”, “DVI-D”, “DVI-A” }",Connector,TBD |
9 | ,,“select subconnector”,ENUM,"{ “Automatic”, “DVI-D”, “DVI-A” }",Connector,TBD | 4 | ,,“select subconnector”,ENUM,"{ “Automatic”, “DVI-D”, “DVI-A” }",Connector,TBD |
10 | ,TV,“subconnector”,ENUM,"{ ""Unknown"", ""Composite"", ""SVIDEO"", ""Component"", ""SCART"" }",Connector,TBD | 5 | ,TV,“subconnector”,ENUM,"{ ""Unknown"", ""Composite"", ""SVIDEO"", ""Component"", ""SCART"" }",Connector,TBD |
diff --git a/Documentation/gpu/todo.rst b/Documentation/gpu/todo.rst index 64e9d16170ce..e255b36b34a3 100644 --- a/Documentation/gpu/todo.rst +++ b/Documentation/gpu/todo.rst | |||
@@ -99,6 +99,30 @@ events for atomic commits correctly. But fixing these bugs is good anyway. | |||
99 | 99 | ||
100 | Contact: Daniel Vetter, respective driver maintainers | 100 | Contact: Daniel Vetter, respective driver maintainers |
101 | 101 | ||
102 | Better manual-upload support for atomic | ||
103 | --------------------------------------- | ||
104 | |||
105 | This would be especially useful for tinydrm: | ||
106 | |||
107 | - Add a struct drm_rect dirty_clip to drm_crtc_state. When duplicating the | ||
108 | crtc state, clear that to the max values, x/y = 0 and w/h = MAX_INT, in | ||
109 | __drm_atomic_helper_crtc_duplicate_state(). | ||
110 | |||
111 | - Move tinydrm_merge_clips into drm_framebuffer.c, dropping the tinydrm_ | ||
112 | prefix ofc and using drm_fb_. drm_framebuffer.c makes sense since this | ||
113 | is a function useful to implement the fb->dirty function. | ||
114 | |||
115 | - Create a new drm_fb_dirty function which does essentially what e.g. | ||
116 | mipi_dbi_fb_dirty does. You can use e.g. drm_atomic_helper_update_plane as the | ||
117 | template. But instead of doing a simple full-screen plane update, this new | ||
118 | helper also sets crtc_state->dirty_clip to the right coordinates. And of | ||
119 | course it needs to check whether the fb is actually active (and maybe where), | ||
120 | so there's some book-keeping involved. There's also some good fun involved in | ||
121 | scaling things appropriately. For that case we might simply give up and | ||
122 | declare the entire area covered by the plane as dirty. | ||
123 | |||
124 | Contact: Noralf Trønnes, Daniel Vetter | ||
125 | |||
102 | Fallout from atomic KMS | 126 | Fallout from atomic KMS |
103 | ----------------------- | 127 | ----------------------- |
104 | 128 | ||
@@ -272,6 +296,32 @@ This is a really varied tasks with lots of little bits and pieces: | |||
272 | 296 | ||
273 | Contact: Daniel Vetter | 297 | Contact: Daniel Vetter |
274 | 298 | ||
299 | Clean up the debugfs support | ||
300 | ---------------------------- | ||
301 | |||
302 | There's a bunch of issues with it: | ||
303 | |||
304 | - The drm_info_list ->show() function doesn't even bother to cast to the drm | ||
305 | structure for you. This is lazy. | ||
306 | |||
307 | - We probably want to have some support for debugfs files on crtc/connectors and | ||
308 | maybe other kms objects directly in core. There's even drm_print support in | ||
309 | the funcs for these objects to dump kms state, so it's all there. And then the | ||
310 | ->show() functions should obviously give you a pointer to the right object. | ||
311 | |||
312 | - The drm_info_list stuff is centered on drm_minor instead of drm_device. For | ||
313 | anything we want to print drm_device (or maybe drm_file) is the right thing. | ||
314 | |||
315 | - The drm_driver->debugfs_init hooks we have is just an artifact of the old | ||
316 | midlayered load sequence. DRM debugfs should work more like sysfs, where you | ||
317 | can create properties/files for an object anytime you want, and the core | ||
318 | takes care of publishing/unpuplishing all the files at register/unregister | ||
319 | time. Drivers shouldn't need to worry about these technicalities, and fixing | ||
320 | this (together with the drm_minor->drm_device move) would allow us to remove | ||
321 | debugfs_init. | ||
322 | |||
323 | Contact: Daniel Vetter | ||
324 | |||
275 | Better Testing | 325 | Better Testing |
276 | ============== | 326 | ============== |
277 | 327 | ||
@@ -310,6 +360,52 @@ Contact: Daniel Vetter | |||
310 | Driver Specific | 360 | Driver Specific |
311 | =============== | 361 | =============== |
312 | 362 | ||
363 | tinydrm | ||
364 | ------- | ||
365 | |||
366 | Tinydrm is the helper driver for really simple fb drivers. The goal is to make | ||
367 | those drivers as simple as possible, so lots of room for refactoring: | ||
368 | |||
369 | - backlight helpers, probably best to put them into a new drm_backlight.c. | ||
370 | This is because drivers/video is de-facto unmaintained. We could also | ||
371 | move drivers/video/backlight to drivers/gpu/backlight and take it all | ||
372 | over within drm-misc, but that's more work. | ||
373 | |||
374 | - spi helpers, probably best put into spi core/helper code. Thierry said | ||
375 | the spi maintainer is fast&reactive, so shouldn't be a big issue. | ||
376 | |||
377 | - extract the mipi-dbi helper (well, the non-tinydrm specific parts at | ||
378 | least) into a separate helper, like we have for mipi-dsi already. Or follow | ||
379 | one of the ideas for having a shared dsi/dbi helper, abstracting away the | ||
380 | transport details more. | ||
381 | |||
382 | - tinydrm_lastclose could be drm_fb_helper_lastclose. Only thing we need | ||
383 | for that is to store the drm_fb_helper pointer somewhere in | ||
384 | drm_device->mode_config. And then we could roll that out to all the | ||
385 | drivers. | ||
386 | |||
387 | - tinydrm_gem_cma_prime_import_sg_table should probably go into the cma | ||
388 | helpers, as a _vmapped variant (since not every driver needs the vmap). | ||
389 | And tinydrm_gem_cma_free_object could the be merged into | ||
390 | drm_gem_cma_free_object(). | ||
391 | |||
392 | - tinydrm_fb_create we could move into drm_simple_pipe, only need to add | ||
393 | the fb_create hook to drm_simple_pipe_funcs, which would again simplify a | ||
394 | bunch of things (since it gives you a one-stop vfunc for simple drivers). | ||
395 | |||
396 | - Quick aside: The unregister devm stuff is kinda getting the lifetimes of | ||
397 | a drm_device wrong. Doesn't matter, since everyone else gets it wrong | ||
398 | too :-) | ||
399 | |||
400 | - With the fbdev pointer in dev->mode_config we could also make | ||
401 | suspend/resume helpers entirely generic, at least if we add a | ||
402 | dev->mode_config.suspend_state. We could even provide a generic pm_ops | ||
403 | structure with those. | ||
404 | |||
405 | - also rework the drm_framebuffer_funcs->dirty hook wire-up, see above. | ||
406 | |||
407 | Contact: Noralf Trønnes, Daniel Vetter | ||
408 | |||
313 | Outside DRM | 409 | Outside DRM |
314 | =========== | 410 | =========== |
315 | 411 | ||
diff --git a/Documentation/process/index.rst b/Documentation/process/index.rst index 10aa6920709a..82fc399fcd33 100644 --- a/Documentation/process/index.rst +++ b/Documentation/process/index.rst | |||
@@ -3,6 +3,7 @@ | |||
3 | \renewcommand\thesection* | 3 | \renewcommand\thesection* |
4 | \renewcommand\thesubsection* | 4 | \renewcommand\thesubsection* |
5 | 5 | ||
6 | .. _process_index: | ||
6 | 7 | ||
7 | Working with the kernel development community | 8 | Working with the kernel development community |
8 | ============================================= | 9 | ============================================= |
diff --git a/MAINTAINERS b/MAINTAINERS index be86eee3353f..fa8479e1799a 100644 --- a/MAINTAINERS +++ b/MAINTAINERS | |||
@@ -4145,6 +4145,7 @@ F: Documentation/devicetree/bindings/video/ | |||
4145 | F: Documentation/gpu/ | 4145 | F: Documentation/gpu/ |
4146 | F: include/drm/ | 4146 | F: include/drm/ |
4147 | F: include/uapi/drm/ | 4147 | F: include/uapi/drm/ |
4148 | F: include/linux/vga* | ||
4148 | 4149 | ||
4149 | DRM DRIVERS AND MISC GPU PATCHES | 4150 | DRM DRIVERS AND MISC GPU PATCHES |
4150 | M: Daniel Vetter <daniel.vetter@intel.com> | 4151 | M: Daniel Vetter <daniel.vetter@intel.com> |
@@ -4158,6 +4159,7 @@ F: drivers/gpu/vga/ | |||
4158 | F: drivers/gpu/drm/* | 4159 | F: drivers/gpu/drm/* |
4159 | F: include/drm/drm* | 4160 | F: include/drm/drm* |
4160 | F: include/uapi/drm/drm* | 4161 | F: include/uapi/drm/drm* |
4162 | F: include/linux/vga* | ||
4161 | 4163 | ||
4162 | DRM DRIVER FOR AST SERVER GRAPHICS CHIPS | 4164 | DRM DRIVER FOR AST SERVER GRAPHICS CHIPS |
4163 | M: Dave Airlie <airlied@redhat.com> | 4165 | M: Dave Airlie <airlied@redhat.com> |
@@ -13257,6 +13259,14 @@ L: kvm@vger.kernel.org | |||
13257 | S: Maintained | 13259 | S: Maintained |
13258 | F: drivers/vfio/platform/ | 13260 | F: drivers/vfio/platform/ |
13259 | 13261 | ||
13262 | VGA_SWITCHEROO | ||
13263 | R: Lukas Wunner <lukas@wunner.de> | ||
13264 | S: Maintained | ||
13265 | F: Documentation/gpu/vga-switcheroo.rst | ||
13266 | F: drivers/gpu/vga/vga_switcheroo.c | ||
13267 | F: include/linux/vga_switcheroo.h | ||
13268 | T: git git://anongit.freedesktop.org/drm/drm-misc | ||
13269 | |||
13260 | VIDEOBUF2 FRAMEWORK | 13270 | VIDEOBUF2 FRAMEWORK |
13261 | M: Pawel Osciak <pawel@osciak.com> | 13271 | M: Pawel Osciak <pawel@osciak.com> |
13262 | M: Marek Szyprowski <m.szyprowski@samsung.com> | 13272 | M: Marek Szyprowski <m.szyprowski@samsung.com> |
diff --git a/drivers/gpu/drm/amd/amdgpu/amdgpu_device.c b/drivers/gpu/drm/amd/amdgpu/amdgpu_device.c index 93061a439dbc..83dda05325b8 100644 --- a/drivers/gpu/drm/amd/amdgpu/amdgpu_device.c +++ b/drivers/gpu/drm/amd/amdgpu/amdgpu_device.c | |||
@@ -1929,7 +1929,9 @@ int amdgpu_device_init(struct amdgpu_device *adev, | |||
1929 | runtime = true; | 1929 | runtime = true; |
1930 | if (amdgpu_device_is_px(ddev)) | 1930 | if (amdgpu_device_is_px(ddev)) |
1931 | runtime = true; | 1931 | runtime = true; |
1932 | vga_switcheroo_register_client(adev->pdev, &amdgpu_switcheroo_ops, runtime); | 1932 | if (!pci_is_thunderbolt_attached(adev->pdev)) |
1933 | vga_switcheroo_register_client(adev->pdev, | ||
1934 | &amdgpu_switcheroo_ops, runtime); | ||
1933 | if (runtime) | 1935 | if (runtime) |
1934 | vga_switcheroo_init_domain_pm_ops(adev->dev, &adev->vga_pm_domain); | 1936 | vga_switcheroo_init_domain_pm_ops(adev->dev, &adev->vga_pm_domain); |
1935 | 1937 | ||
@@ -2084,7 +2086,8 @@ void amdgpu_device_fini(struct amdgpu_device *adev) | |||
2084 | amdgpu_atombios_fini(adev); | 2086 | amdgpu_atombios_fini(adev); |
2085 | kfree(adev->bios); | 2087 | kfree(adev->bios); |
2086 | adev->bios = NULL; | 2088 | adev->bios = NULL; |
2087 | vga_switcheroo_unregister_client(adev->pdev); | 2089 | if (!pci_is_thunderbolt_attached(adev->pdev)) |
2090 | vga_switcheroo_unregister_client(adev->pdev); | ||
2088 | if (adev->flags & AMD_IS_PX) | 2091 | if (adev->flags & AMD_IS_PX) |
2089 | vga_switcheroo_fini_domain_pm_ops(adev->dev); | 2092 | vga_switcheroo_fini_domain_pm_ops(adev->dev); |
2090 | vga_client_register(adev->pdev, NULL, NULL, NULL); | 2093 | vga_client_register(adev->pdev, NULL, NULL, NULL); |
diff --git a/drivers/gpu/drm/amd/amdgpu/amdgpu_display.c b/drivers/gpu/drm/amd/amdgpu/amdgpu_display.c index 39fc388f222a..ce15721cadda 100644 --- a/drivers/gpu/drm/amd/amdgpu/amdgpu_display.c +++ b/drivers/gpu/drm/amd/amdgpu/amdgpu_display.c | |||
@@ -311,7 +311,8 @@ int amdgpu_crtc_page_flip_target(struct drm_crtc *crtc, | |||
311 | struct drm_framebuffer *fb, | 311 | struct drm_framebuffer *fb, |
312 | struct drm_pending_vblank_event *event, | 312 | struct drm_pending_vblank_event *event, |
313 | uint32_t page_flip_flags, | 313 | uint32_t page_flip_flags, |
314 | uint32_t target) | 314 | uint32_t target, |
315 | struct drm_modeset_acquire_ctx *ctx) | ||
315 | { | 316 | { |
316 | struct amdgpu_bo *new_abo; | 317 | struct amdgpu_bo *new_abo; |
317 | struct amdgpu_flip_work *work; | 318 | struct amdgpu_flip_work *work; |
@@ -332,7 +333,8 @@ int amdgpu_crtc_page_flip_target(struct drm_crtc *crtc, | |||
332 | return 0; | 333 | return 0; |
333 | } | 334 | } |
334 | 335 | ||
335 | int amdgpu_crtc_set_config(struct drm_mode_set *set) | 336 | int amdgpu_crtc_set_config(struct drm_mode_set *set, |
337 | struct drm_modeset_acquire_ctx *ctx) | ||
336 | { | 338 | { |
337 | struct drm_device *dev; | 339 | struct drm_device *dev; |
338 | struct amdgpu_device *adev; | 340 | struct amdgpu_device *adev; |
@@ -349,7 +351,7 @@ int amdgpu_crtc_set_config(struct drm_mode_set *set) | |||
349 | if (ret < 0) | 351 | if (ret < 0) |
350 | return ret; | 352 | return ret; |
351 | 353 | ||
352 | ret = drm_crtc_helper_set_config(set); | 354 | ret = drm_crtc_helper_set_config(set, ctx); |
353 | 355 | ||
354 | list_for_each_entry(crtc, &dev->mode_config.crtc_list, head) | 356 | list_for_each_entry(crtc, &dev->mode_config.crtc_list, head) |
355 | if (crtc->enabled) | 357 | if (crtc->enabled) |
diff --git a/drivers/gpu/drm/amd/amdgpu/amdgpu_kms.c b/drivers/gpu/drm/amd/amdgpu/amdgpu_kms.c index 5ded370a4b35..dfb029ab3448 100644 --- a/drivers/gpu/drm/amd/amdgpu/amdgpu_kms.c +++ b/drivers/gpu/drm/amd/amdgpu/amdgpu_kms.c | |||
@@ -103,7 +103,8 @@ int amdgpu_driver_load_kms(struct drm_device *dev, unsigned long flags) | |||
103 | amdgpu_has_atpx() && | 103 | amdgpu_has_atpx() && |
104 | (amdgpu_is_atpx_hybrid() || | 104 | (amdgpu_is_atpx_hybrid() || |
105 | amdgpu_has_atpx_dgpu_power_cntl()) && | 105 | amdgpu_has_atpx_dgpu_power_cntl()) && |
106 | ((flags & AMD_IS_APU) == 0)) | 106 | ((flags & AMD_IS_APU) == 0) && |
107 | !pci_is_thunderbolt_attached(dev->pdev)) | ||
107 | flags |= AMD_IS_PX; | 108 | flags |= AMD_IS_PX; |
108 | 109 | ||
109 | /* amdgpu_device_init should report only fatal error | 110 | /* amdgpu_device_init should report only fatal error |
diff --git a/drivers/gpu/drm/amd/amdgpu/amdgpu_mode.h b/drivers/gpu/drm/amd/amdgpu/amdgpu_mode.h index c12497bd3889..db8f8dda209c 100644 --- a/drivers/gpu/drm/amd/amdgpu/amdgpu_mode.h +++ b/drivers/gpu/drm/amd/amdgpu/amdgpu_mode.h | |||
@@ -590,11 +590,13 @@ int amdgpu_align_pitch(struct amdgpu_device *adev, int width, int bpp, bool tile | |||
590 | /* amdgpu_display.c */ | 590 | /* amdgpu_display.c */ |
591 | void amdgpu_print_display_setup(struct drm_device *dev); | 591 | void amdgpu_print_display_setup(struct drm_device *dev); |
592 | int amdgpu_modeset_create_props(struct amdgpu_device *adev); | 592 | int amdgpu_modeset_create_props(struct amdgpu_device *adev); |
593 | int amdgpu_crtc_set_config(struct drm_mode_set *set); | 593 | int amdgpu_crtc_set_config(struct drm_mode_set *set, |
594 | struct drm_modeset_acquire_ctx *ctx); | ||
594 | int amdgpu_crtc_page_flip_target(struct drm_crtc *crtc, | 595 | int amdgpu_crtc_page_flip_target(struct drm_crtc *crtc, |
595 | struct drm_framebuffer *fb, | 596 | struct drm_framebuffer *fb, |
596 | struct drm_pending_vblank_event *event, | 597 | struct drm_pending_vblank_event *event, |
597 | uint32_t page_flip_flags, uint32_t target); | 598 | uint32_t page_flip_flags, uint32_t target, |
599 | struct drm_modeset_acquire_ctx *ctx); | ||
598 | void amdgpu_crtc_cleanup_flip_ctx(struct amdgpu_flip_work *work, | 600 | void amdgpu_crtc_cleanup_flip_ctx(struct amdgpu_flip_work *work, |
599 | struct amdgpu_bo *new_abo); | 601 | struct amdgpu_bo *new_abo); |
600 | int amdgpu_crtc_prepare_flip(struct drm_crtc *crtc, | 602 | int amdgpu_crtc_prepare_flip(struct drm_crtc *crtc, |
diff --git a/drivers/gpu/drm/armada/armada_crtc.c b/drivers/gpu/drm/armada/armada_crtc.c index 1341e0b9368a..4fe19fde84f9 100644 --- a/drivers/gpu/drm/armada/armada_crtc.c +++ b/drivers/gpu/drm/armada/armada_crtc.c | |||
@@ -1027,7 +1027,8 @@ static void armada_drm_crtc_destroy(struct drm_crtc *crtc) | |||
1027 | * and a mode_set. | 1027 | * and a mode_set. |
1028 | */ | 1028 | */ |
1029 | static int armada_drm_crtc_page_flip(struct drm_crtc *crtc, | 1029 | static int armada_drm_crtc_page_flip(struct drm_crtc *crtc, |
1030 | struct drm_framebuffer *fb, struct drm_pending_vblank_event *event, uint32_t page_flip_flags) | 1030 | struct drm_framebuffer *fb, struct drm_pending_vblank_event *event, uint32_t page_flip_flags, |
1031 | struct drm_modeset_acquire_ctx *ctx) | ||
1031 | { | 1032 | { |
1032 | struct armada_crtc *dcrtc = drm_to_armada_crtc(crtc); | 1033 | struct armada_crtc *dcrtc = drm_to_armada_crtc(crtc); |
1033 | struct armada_frame_work *work; | 1034 | struct armada_frame_work *work; |
diff --git a/drivers/gpu/drm/armada/armada_overlay.c b/drivers/gpu/drm/armada/armada_overlay.c index 34cb73d0db77..424e465ff407 100644 --- a/drivers/gpu/drm/armada/armada_overlay.c +++ b/drivers/gpu/drm/armada/armada_overlay.c | |||
@@ -94,7 +94,8 @@ static int | |||
94 | armada_ovl_plane_update(struct drm_plane *plane, struct drm_crtc *crtc, | 94 | armada_ovl_plane_update(struct drm_plane *plane, struct drm_crtc *crtc, |
95 | struct drm_framebuffer *fb, | 95 | struct drm_framebuffer *fb, |
96 | int crtc_x, int crtc_y, unsigned crtc_w, unsigned crtc_h, | 96 | int crtc_x, int crtc_y, unsigned crtc_w, unsigned crtc_h, |
97 | uint32_t src_x, uint32_t src_y, uint32_t src_w, uint32_t src_h) | 97 | uint32_t src_x, uint32_t src_y, uint32_t src_w, uint32_t src_h, |
98 | struct drm_modeset_acquire_ctx *ctx) | ||
98 | { | 99 | { |
99 | struct armada_ovl_plane *dplane = drm_to_armada_ovl_plane(plane); | 100 | struct armada_ovl_plane *dplane = drm_to_armada_ovl_plane(plane); |
100 | struct armada_crtc *dcrtc = drm_to_armada_crtc(crtc); | 101 | struct armada_crtc *dcrtc = drm_to_armada_crtc(crtc); |
@@ -257,7 +258,8 @@ armada_ovl_plane_update(struct drm_plane *plane, struct drm_crtc *crtc, | |||
257 | return 0; | 258 | return 0; |
258 | } | 259 | } |
259 | 260 | ||
260 | static int armada_ovl_plane_disable(struct drm_plane *plane) | 261 | static int armada_ovl_plane_disable(struct drm_plane *plane, |
262 | struct drm_modeset_acquire_ctx *ctx) | ||
261 | { | 263 | { |
262 | struct armada_ovl_plane *dplane = drm_to_armada_ovl_plane(plane); | 264 | struct armada_ovl_plane *dplane = drm_to_armada_ovl_plane(plane); |
263 | struct drm_framebuffer *fb; | 265 | struct drm_framebuffer *fb; |
diff --git a/drivers/gpu/drm/bochs/bochs_fbdev.c b/drivers/gpu/drm/bochs/bochs_fbdev.c index 471bd588550b..c38deffa14de 100644 --- a/drivers/gpu/drm/bochs/bochs_fbdev.c +++ b/drivers/gpu/drm/bochs/bochs_fbdev.c | |||
@@ -192,6 +192,8 @@ void bochs_fbdev_fini(struct bochs_device *bochs) | |||
192 | if (bochs->fb.initialized) | 192 | if (bochs->fb.initialized) |
193 | bochs_fbdev_destroy(bochs); | 193 | bochs_fbdev_destroy(bochs); |
194 | 194 | ||
195 | drm_fb_helper_fini(&bochs->fb.helper); | 195 | if (bochs->fb.helper.fbdev) |
196 | drm_fb_helper_fini(&bochs->fb.helper); | ||
197 | |||
196 | bochs->fb.initialized = false; | 198 | bochs->fb.initialized = false; |
197 | } | 199 | } |
diff --git a/drivers/gpu/drm/bochs/bochs_kms.c b/drivers/gpu/drm/bochs/bochs_kms.c index d5e63eff357b..6a91e62da2f4 100644 --- a/drivers/gpu/drm/bochs/bochs_kms.c +++ b/drivers/gpu/drm/bochs/bochs_kms.c | |||
@@ -96,7 +96,8 @@ static void bochs_crtc_commit(struct drm_crtc *crtc) | |||
96 | static int bochs_crtc_page_flip(struct drm_crtc *crtc, | 96 | static int bochs_crtc_page_flip(struct drm_crtc *crtc, |
97 | struct drm_framebuffer *fb, | 97 | struct drm_framebuffer *fb, |
98 | struct drm_pending_vblank_event *event, | 98 | struct drm_pending_vblank_event *event, |
99 | uint32_t page_flip_flags) | 99 | uint32_t page_flip_flags, |
100 | struct drm_modeset_acquire_ctx *ctx) | ||
100 | { | 101 | { |
101 | struct bochs_device *bochs = | 102 | struct bochs_device *bochs = |
102 | container_of(crtc, struct bochs_device, crtc); | 103 | container_of(crtc, struct bochs_device, crtc); |
diff --git a/drivers/gpu/drm/bridge/synopsys/dw-hdmi.c b/drivers/gpu/drm/bridge/synopsys/dw-hdmi.c index af93f7a20697..32f02e92e0b9 100644 --- a/drivers/gpu/drm/bridge/synopsys/dw-hdmi.c +++ b/drivers/gpu/drm/bridge/synopsys/dw-hdmi.c | |||
@@ -1916,7 +1916,7 @@ static irqreturn_t dw_hdmi_irq(int irq, void *dev_id) | |||
1916 | if (intr_stat & | 1916 | if (intr_stat & |
1917 | (HDMI_IH_PHY_STAT0_RX_SENSE | HDMI_IH_PHY_STAT0_HPD)) { | 1917 | (HDMI_IH_PHY_STAT0_RX_SENSE | HDMI_IH_PHY_STAT0_HPD)) { |
1918 | mutex_lock(&hdmi->mutex); | 1918 | mutex_lock(&hdmi->mutex); |
1919 | if (!hdmi->disabled && !hdmi->force) { | 1919 | if (!hdmi->force) { |
1920 | /* | 1920 | /* |
1921 | * If the RX sense status indicates we're disconnected, | 1921 | * If the RX sense status indicates we're disconnected, |
1922 | * clear the software rxsense status. | 1922 | * clear the software rxsense status. |
diff --git a/drivers/gpu/drm/bridge/ti-tfp410.c b/drivers/gpu/drm/bridge/ti-tfp410.c index b379d046991b..7d519b46aee4 100644 --- a/drivers/gpu/drm/bridge/ti-tfp410.c +++ b/drivers/gpu/drm/bridge/ti-tfp410.c | |||
@@ -8,6 +8,10 @@ | |||
8 | * | 8 | * |
9 | */ | 9 | */ |
10 | 10 | ||
11 | #include <linux/delay.h> | ||
12 | #include <linux/fwnode.h> | ||
13 | #include <linux/gpio/consumer.h> | ||
14 | #include <linux/irq.h> | ||
11 | #include <linux/module.h> | 15 | #include <linux/module.h> |
12 | #include <linux/of_graph.h> | 16 | #include <linux/of_graph.h> |
13 | #include <linux/platform_device.h> | 17 | #include <linux/platform_device.h> |
@@ -18,11 +22,15 @@ | |||
18 | #include <drm/drm_crtc.h> | 22 | #include <drm/drm_crtc.h> |
19 | #include <drm/drm_crtc_helper.h> | 23 | #include <drm/drm_crtc_helper.h> |
20 | 24 | ||
25 | #define HOTPLUG_DEBOUNCE_MS 1100 | ||
26 | |||
21 | struct tfp410 { | 27 | struct tfp410 { |
22 | struct drm_bridge bridge; | 28 | struct drm_bridge bridge; |
23 | struct drm_connector connector; | 29 | struct drm_connector connector; |
24 | 30 | ||
25 | struct i2c_adapter *ddc; | 31 | struct i2c_adapter *ddc; |
32 | struct gpio_desc *hpd; | ||
33 | struct delayed_work hpd_work; | ||
26 | 34 | ||
27 | struct device *dev; | 35 | struct device *dev; |
28 | }; | 36 | }; |
@@ -76,6 +84,13 @@ tfp410_connector_detect(struct drm_connector *connector, bool force) | |||
76 | { | 84 | { |
77 | struct tfp410 *dvi = drm_connector_to_tfp410(connector); | 85 | struct tfp410 *dvi = drm_connector_to_tfp410(connector); |
78 | 86 | ||
87 | if (dvi->hpd) { | ||
88 | if (gpiod_get_value_cansleep(dvi->hpd)) | ||
89 | return connector_status_connected; | ||
90 | else | ||
91 | return connector_status_disconnected; | ||
92 | } | ||
93 | |||
79 | if (dvi->ddc) { | 94 | if (dvi->ddc) { |
80 | if (drm_probe_ddc(dvi->ddc)) | 95 | if (drm_probe_ddc(dvi->ddc)) |
81 | return connector_status_connected; | 96 | return connector_status_connected; |
@@ -106,6 +121,9 @@ static int tfp410_attach(struct drm_bridge *bridge) | |||
106 | return -ENODEV; | 121 | return -ENODEV; |
107 | } | 122 | } |
108 | 123 | ||
124 | if (dvi->hpd) | ||
125 | dvi->connector.polled = DRM_CONNECTOR_POLL_HPD; | ||
126 | |||
109 | drm_connector_helper_add(&dvi->connector, | 127 | drm_connector_helper_add(&dvi->connector, |
110 | &tfp410_con_helper_funcs); | 128 | &tfp410_con_helper_funcs); |
111 | ret = drm_connector_init(bridge->dev, &dvi->connector, | 129 | ret = drm_connector_init(bridge->dev, &dvi->connector, |
@@ -125,7 +143,27 @@ static const struct drm_bridge_funcs tfp410_bridge_funcs = { | |||
125 | .attach = tfp410_attach, | 143 | .attach = tfp410_attach, |
126 | }; | 144 | }; |
127 | 145 | ||
128 | static int tfp410_get_connector_ddc(struct tfp410 *dvi) | 146 | static void tfp410_hpd_work_func(struct work_struct *work) |
147 | { | ||
148 | struct tfp410 *dvi; | ||
149 | |||
150 | dvi = container_of(work, struct tfp410, hpd_work.work); | ||
151 | |||
152 | if (dvi->bridge.dev) | ||
153 | drm_helper_hpd_irq_event(dvi->bridge.dev); | ||
154 | } | ||
155 | |||
156 | static irqreturn_t tfp410_hpd_irq_thread(int irq, void *arg) | ||
157 | { | ||
158 | struct tfp410 *dvi = arg; | ||
159 | |||
160 | mod_delayed_work(system_wq, &dvi->hpd_work, | ||
161 | msecs_to_jiffies(HOTPLUG_DEBOUNCE_MS)); | ||
162 | |||
163 | return IRQ_HANDLED; | ||
164 | } | ||
165 | |||
166 | static int tfp410_get_connector_properties(struct tfp410 *dvi) | ||
129 | { | 167 | { |
130 | struct device_node *ep = NULL, *connector_node = NULL; | 168 | struct device_node *ep = NULL, *connector_node = NULL; |
131 | struct device_node *ddc_phandle = NULL; | 169 | struct device_node *ddc_phandle = NULL; |
@@ -140,6 +178,17 @@ static int tfp410_get_connector_ddc(struct tfp410 *dvi) | |||
140 | if (!connector_node) | 178 | if (!connector_node) |
141 | goto fail; | 179 | goto fail; |
142 | 180 | ||
181 | dvi->hpd = fwnode_get_named_gpiod(&connector_node->fwnode, | ||
182 | "hpd-gpios", 0, GPIOD_IN, "hpd"); | ||
183 | if (IS_ERR(dvi->hpd)) { | ||
184 | ret = PTR_ERR(dvi->hpd); | ||
185 | dvi->hpd = NULL; | ||
186 | if (ret == -ENOENT) | ||
187 | ret = 0; | ||
188 | else | ||
189 | goto fail; | ||
190 | } | ||
191 | |||
143 | ddc_phandle = of_parse_phandle(connector_node, "ddc-i2c-bus", 0); | 192 | ddc_phandle = of_parse_phandle(connector_node, "ddc-i2c-bus", 0); |
144 | if (!ddc_phandle) | 193 | if (!ddc_phandle) |
145 | goto fail; | 194 | goto fail; |
@@ -176,10 +225,23 @@ static int tfp410_init(struct device *dev) | |||
176 | dvi->bridge.of_node = dev->of_node; | 225 | dvi->bridge.of_node = dev->of_node; |
177 | dvi->dev = dev; | 226 | dvi->dev = dev; |
178 | 227 | ||
179 | ret = tfp410_get_connector_ddc(dvi); | 228 | ret = tfp410_get_connector_properties(dvi); |
180 | if (ret) | 229 | if (ret) |
181 | goto fail; | 230 | goto fail; |
182 | 231 | ||
232 | if (dvi->hpd) { | ||
233 | INIT_DELAYED_WORK(&dvi->hpd_work, tfp410_hpd_work_func); | ||
234 | |||
235 | ret = devm_request_threaded_irq(dev, gpiod_to_irq(dvi->hpd), | ||
236 | NULL, tfp410_hpd_irq_thread, IRQF_TRIGGER_RISING | | ||
237 | IRQF_TRIGGER_FALLING | IRQF_ONESHOT, | ||
238 | "hdmi-hpd", dvi); | ||
239 | if (ret) { | ||
240 | DRM_ERROR("failed to register hpd interrupt\n"); | ||
241 | goto fail; | ||
242 | } | ||
243 | } | ||
244 | |||
183 | ret = drm_bridge_add(&dvi->bridge); | 245 | ret = drm_bridge_add(&dvi->bridge); |
184 | if (ret) { | 246 | if (ret) { |
185 | dev_err(dev, "drm_bridge_add() failed: %d\n", ret); | 247 | dev_err(dev, "drm_bridge_add() failed: %d\n", ret); |
@@ -189,6 +251,8 @@ static int tfp410_init(struct device *dev) | |||
189 | return 0; | 251 | return 0; |
190 | fail: | 252 | fail: |
191 | i2c_put_adapter(dvi->ddc); | 253 | i2c_put_adapter(dvi->ddc); |
254 | if (dvi->hpd) | ||
255 | gpiod_put(dvi->hpd); | ||
192 | return ret; | 256 | return ret; |
193 | } | 257 | } |
194 | 258 | ||
@@ -196,10 +260,14 @@ static int tfp410_fini(struct device *dev) | |||
196 | { | 260 | { |
197 | struct tfp410 *dvi = dev_get_drvdata(dev); | 261 | struct tfp410 *dvi = dev_get_drvdata(dev); |
198 | 262 | ||
263 | cancel_delayed_work_sync(&dvi->hpd_work); | ||
264 | |||
199 | drm_bridge_remove(&dvi->bridge); | 265 | drm_bridge_remove(&dvi->bridge); |
200 | 266 | ||
201 | if (dvi->ddc) | 267 | if (dvi->ddc) |
202 | i2c_put_adapter(dvi->ddc); | 268 | i2c_put_adapter(dvi->ddc); |
269 | if (dvi->hpd) | ||
270 | gpiod_put(dvi->hpd); | ||
203 | 271 | ||
204 | return 0; | 272 | return 0; |
205 | } | 273 | } |
diff --git a/drivers/gpu/drm/drm_atomic_helper.c b/drivers/gpu/drm/drm_atomic_helper.c index 4e26b73bb0d5..c3994b4d5f32 100644 --- a/drivers/gpu/drm/drm_atomic_helper.c +++ b/drivers/gpu/drm/drm_atomic_helper.c | |||
@@ -2077,6 +2077,7 @@ EXPORT_SYMBOL(drm_atomic_helper_swap_state); | |||
2077 | * @src_y: y offset of @fb for panning | 2077 | * @src_y: y offset of @fb for panning |
2078 | * @src_w: width of source rectangle in @fb | 2078 | * @src_w: width of source rectangle in @fb |
2079 | * @src_h: height of source rectangle in @fb | 2079 | * @src_h: height of source rectangle in @fb |
2080 | * @ctx: lock acquire context | ||
2080 | * | 2081 | * |
2081 | * Provides a default plane update handler using the atomic driver interface. | 2082 | * Provides a default plane update handler using the atomic driver interface. |
2082 | * | 2083 | * |
@@ -2089,7 +2090,8 @@ int drm_atomic_helper_update_plane(struct drm_plane *plane, | |||
2089 | int crtc_x, int crtc_y, | 2090 | int crtc_x, int crtc_y, |
2090 | unsigned int crtc_w, unsigned int crtc_h, | 2091 | unsigned int crtc_w, unsigned int crtc_h, |
2091 | uint32_t src_x, uint32_t src_y, | 2092 | uint32_t src_x, uint32_t src_y, |
2092 | uint32_t src_w, uint32_t src_h) | 2093 | uint32_t src_w, uint32_t src_h, |
2094 | struct drm_modeset_acquire_ctx *ctx) | ||
2093 | { | 2095 | { |
2094 | struct drm_atomic_state *state; | 2096 | struct drm_atomic_state *state; |
2095 | struct drm_plane_state *plane_state; | 2097 | struct drm_plane_state *plane_state; |
@@ -2099,8 +2101,7 @@ int drm_atomic_helper_update_plane(struct drm_plane *plane, | |||
2099 | if (!state) | 2101 | if (!state) |
2100 | return -ENOMEM; | 2102 | return -ENOMEM; |
2101 | 2103 | ||
2102 | state->acquire_ctx = drm_modeset_legacy_acquire_ctx(crtc); | 2104 | state->acquire_ctx = ctx; |
2103 | retry: | ||
2104 | plane_state = drm_atomic_get_plane_state(state, plane); | 2105 | plane_state = drm_atomic_get_plane_state(state, plane); |
2105 | if (IS_ERR(plane_state)) { | 2106 | if (IS_ERR(plane_state)) { |
2106 | ret = PTR_ERR(plane_state); | 2107 | ret = PTR_ERR(plane_state); |
@@ -2125,59 +2126,33 @@ retry: | |||
2125 | 2126 | ||
2126 | ret = drm_atomic_commit(state); | 2127 | ret = drm_atomic_commit(state); |
2127 | fail: | 2128 | fail: |
2128 | if (ret == -EDEADLK) | ||
2129 | goto backoff; | ||
2130 | |||
2131 | drm_atomic_state_put(state); | 2129 | drm_atomic_state_put(state); |
2132 | return ret; | 2130 | return ret; |
2133 | |||
2134 | backoff: | ||
2135 | drm_atomic_state_clear(state); | ||
2136 | drm_atomic_legacy_backoff(state); | ||
2137 | |||
2138 | /* | ||
2139 | * Someone might have exchanged the framebuffer while we dropped locks | ||
2140 | * in the backoff code. We need to fix up the fb refcount tracking the | ||
2141 | * core does for us. | ||
2142 | */ | ||
2143 | plane->old_fb = plane->fb; | ||
2144 | |||
2145 | goto retry; | ||
2146 | } | 2131 | } |
2147 | EXPORT_SYMBOL(drm_atomic_helper_update_plane); | 2132 | EXPORT_SYMBOL(drm_atomic_helper_update_plane); |
2148 | 2133 | ||
2149 | /** | 2134 | /** |
2150 | * drm_atomic_helper_disable_plane - Helper for primary plane disable using * atomic | 2135 | * drm_atomic_helper_disable_plane - Helper for primary plane disable using * atomic |
2151 | * @plane: plane to disable | 2136 | * @plane: plane to disable |
2137 | * @ctx: lock acquire context | ||
2152 | * | 2138 | * |
2153 | * Provides a default plane disable handler using the atomic driver interface. | 2139 | * Provides a default plane disable handler using the atomic driver interface. |
2154 | * | 2140 | * |
2155 | * RETURNS: | 2141 | * RETURNS: |
2156 | * Zero on success, error code on failure | 2142 | * Zero on success, error code on failure |
2157 | */ | 2143 | */ |
2158 | int drm_atomic_helper_disable_plane(struct drm_plane *plane) | 2144 | int drm_atomic_helper_disable_plane(struct drm_plane *plane, |
2145 | struct drm_modeset_acquire_ctx *ctx) | ||
2159 | { | 2146 | { |
2160 | struct drm_atomic_state *state; | 2147 | struct drm_atomic_state *state; |
2161 | struct drm_plane_state *plane_state; | 2148 | struct drm_plane_state *plane_state; |
2162 | int ret = 0; | 2149 | int ret = 0; |
2163 | 2150 | ||
2164 | /* | ||
2165 | * FIXME: Without plane->crtc set we can't get at the implicit legacy | ||
2166 | * acquire context. The real fix will be to wire the acquire ctx through | ||
2167 | * everywhere we need it, but meanwhile prevent chaos by just skipping | ||
2168 | * this noop. The critical case is the cursor ioctls which a) only grab | ||
2169 | * crtc/cursor-plane locks (so we need the crtc to get at the right | ||
2170 | * acquire context) and b) can try to disable the plane multiple times. | ||
2171 | */ | ||
2172 | if (!plane->crtc) | ||
2173 | return 0; | ||
2174 | |||
2175 | state = drm_atomic_state_alloc(plane->dev); | 2151 | state = drm_atomic_state_alloc(plane->dev); |
2176 | if (!state) | 2152 | if (!state) |
2177 | return -ENOMEM; | 2153 | return -ENOMEM; |
2178 | 2154 | ||
2179 | state->acquire_ctx = drm_modeset_legacy_acquire_ctx(plane->crtc); | 2155 | state->acquire_ctx = ctx; |
2180 | retry: | ||
2181 | plane_state = drm_atomic_get_plane_state(state, plane); | 2156 | plane_state = drm_atomic_get_plane_state(state, plane); |
2182 | if (IS_ERR(plane_state)) { | 2157 | if (IS_ERR(plane_state)) { |
2183 | ret = PTR_ERR(plane_state); | 2158 | ret = PTR_ERR(plane_state); |
@@ -2193,24 +2168,8 @@ retry: | |||
2193 | 2168 | ||
2194 | ret = drm_atomic_commit(state); | 2169 | ret = drm_atomic_commit(state); |
2195 | fail: | 2170 | fail: |
2196 | if (ret == -EDEADLK) | ||
2197 | goto backoff; | ||
2198 | |||
2199 | drm_atomic_state_put(state); | 2171 | drm_atomic_state_put(state); |
2200 | return ret; | 2172 | return ret; |
2201 | |||
2202 | backoff: | ||
2203 | drm_atomic_state_clear(state); | ||
2204 | drm_atomic_legacy_backoff(state); | ||
2205 | |||
2206 | /* | ||
2207 | * Someone might have exchanged the framebuffer while we dropped locks | ||
2208 | * in the backoff code. We need to fix up the fb refcount tracking the | ||
2209 | * core does for us. | ||
2210 | */ | ||
2211 | plane->old_fb = plane->fb; | ||
2212 | |||
2213 | goto retry; | ||
2214 | } | 2173 | } |
2215 | EXPORT_SYMBOL(drm_atomic_helper_disable_plane); | 2174 | EXPORT_SYMBOL(drm_atomic_helper_disable_plane); |
2216 | 2175 | ||
@@ -2306,6 +2265,7 @@ static int update_output_state(struct drm_atomic_state *state, | |||
2306 | /** | 2265 | /** |
2307 | * drm_atomic_helper_set_config - set a new config from userspace | 2266 | * drm_atomic_helper_set_config - set a new config from userspace |
2308 | * @set: mode set configuration | 2267 | * @set: mode set configuration |
2268 | * @ctx: lock acquisition context | ||
2309 | * | 2269 | * |
2310 | * Provides a default crtc set_config handler using the atomic driver interface. | 2270 | * Provides a default crtc set_config handler using the atomic driver interface. |
2311 | * | 2271 | * |
@@ -2318,7 +2278,8 @@ static int update_output_state(struct drm_atomic_state *state, | |||
2318 | * Returns: | 2278 | * Returns: |
2319 | * Returns 0 on success, negative errno numbers on failure. | 2279 | * Returns 0 on success, negative errno numbers on failure. |
2320 | */ | 2280 | */ |
2321 | int drm_atomic_helper_set_config(struct drm_mode_set *set) | 2281 | int drm_atomic_helper_set_config(struct drm_mode_set *set, |
2282 | struct drm_modeset_acquire_ctx *ctx) | ||
2322 | { | 2283 | { |
2323 | struct drm_atomic_state *state; | 2284 | struct drm_atomic_state *state; |
2324 | struct drm_crtc *crtc = set->crtc; | 2285 | struct drm_crtc *crtc = set->crtc; |
@@ -2329,32 +2290,16 @@ int drm_atomic_helper_set_config(struct drm_mode_set *set) | |||
2329 | return -ENOMEM; | 2290 | return -ENOMEM; |
2330 | 2291 | ||
2331 | state->legacy_set_config = true; | 2292 | state->legacy_set_config = true; |
2332 | state->acquire_ctx = drm_modeset_legacy_acquire_ctx(crtc); | 2293 | state->acquire_ctx = ctx; |
2333 | retry: | ||
2334 | ret = __drm_atomic_helper_set_config(set, state); | 2294 | ret = __drm_atomic_helper_set_config(set, state); |
2335 | if (ret != 0) | 2295 | if (ret != 0) |
2336 | goto fail; | 2296 | goto fail; |
2337 | 2297 | ||
2338 | ret = drm_atomic_commit(state); | 2298 | ret = drm_atomic_commit(state); |
2339 | fail: | ||
2340 | if (ret == -EDEADLK) | ||
2341 | goto backoff; | ||
2342 | 2299 | ||
2300 | fail: | ||
2343 | drm_atomic_state_put(state); | 2301 | drm_atomic_state_put(state); |
2344 | return ret; | 2302 | return ret; |
2345 | |||
2346 | backoff: | ||
2347 | drm_atomic_state_clear(state); | ||
2348 | drm_atomic_legacy_backoff(state); | ||
2349 | |||
2350 | /* | ||
2351 | * Someone might have exchanged the framebuffer while we dropped locks | ||
2352 | * in the backoff code. We need to fix up the fb refcount tracking the | ||
2353 | * core does for us. | ||
2354 | */ | ||
2355 | crtc->primary->old_fb = crtc->primary->fb; | ||
2356 | |||
2357 | goto retry; | ||
2358 | } | 2303 | } |
2359 | EXPORT_SYMBOL(drm_atomic_helper_set_config); | 2304 | EXPORT_SYMBOL(drm_atomic_helper_set_config); |
2360 | 2305 | ||
@@ -2443,7 +2388,8 @@ commit: | |||
2443 | * that they are connected to. | 2388 | * that they are connected to. |
2444 | * | 2389 | * |
2445 | * This is used for example in suspend/resume to disable all currently active | 2390 | * This is used for example in suspend/resume to disable all currently active |
2446 | * functions when suspending. | 2391 | * functions when suspending. If you just want to shut down everything at e.g. |
2392 | * driver unload, look at drm_atomic_helper_shutdown(). | ||
2447 | * | 2393 | * |
2448 | * Note that if callers haven't already acquired all modeset locks this might | 2394 | * Note that if callers haven't already acquired all modeset locks this might |
2449 | * return -EDEADLK, which must be handled by calling drm_modeset_backoff(). | 2395 | * return -EDEADLK, which must be handled by calling drm_modeset_backoff(). |
@@ -2452,7 +2398,8 @@ commit: | |||
2452 | * 0 on success or a negative error code on failure. | 2398 | * 0 on success or a negative error code on failure. |
2453 | * | 2399 | * |
2454 | * See also: | 2400 | * See also: |
2455 | * drm_atomic_helper_suspend(), drm_atomic_helper_resume() | 2401 | * drm_atomic_helper_suspend(), drm_atomic_helper_resume() and |
2402 | * drm_atomic_helper_shutdown(). | ||
2456 | */ | 2403 | */ |
2457 | int drm_atomic_helper_disable_all(struct drm_device *dev, | 2404 | int drm_atomic_helper_disable_all(struct drm_device *dev, |
2458 | struct drm_modeset_acquire_ctx *ctx) | 2405 | struct drm_modeset_acquire_ctx *ctx) |
@@ -2517,6 +2464,42 @@ free: | |||
2517 | EXPORT_SYMBOL(drm_atomic_helper_disable_all); | 2464 | EXPORT_SYMBOL(drm_atomic_helper_disable_all); |
2518 | 2465 | ||
2519 | /** | 2466 | /** |
2467 | * drm_atomic_helper_shutdown - shutdown all CRTC | ||
2468 | * @dev: DRM device | ||
2469 | * | ||
2470 | * This shuts down all CRTC, which is useful for driver unloading. Shutdown on | ||
2471 | * suspend should instead be handled with drm_atomic_helper_suspend(), since | ||
2472 | * that also takes a snapshot of the modeset state to be restored on resume. | ||
2473 | * | ||
2474 | * This is just a convenience wrapper around drm_atomic_helper_disable_all(), | ||
2475 | * and it is the atomic version of drm_crtc_force_disable_all(). | ||
2476 | */ | ||
2477 | void drm_atomic_helper_shutdown(struct drm_device *dev) | ||
2478 | { | ||
2479 | struct drm_modeset_acquire_ctx ctx; | ||
2480 | int ret; | ||
2481 | |||
2482 | drm_modeset_acquire_init(&ctx, 0); | ||
2483 | while (1) { | ||
2484 | ret = drm_modeset_lock_all_ctx(dev, &ctx); | ||
2485 | if (!ret) | ||
2486 | ret = drm_atomic_helper_disable_all(dev, &ctx); | ||
2487 | |||
2488 | if (ret != -EDEADLK) | ||
2489 | break; | ||
2490 | |||
2491 | drm_modeset_backoff(&ctx); | ||
2492 | } | ||
2493 | |||
2494 | if (ret) | ||
2495 | DRM_ERROR("Disabling all crtc's during unload failed with %i\n", ret); | ||
2496 | |||
2497 | drm_modeset_drop_locks(&ctx); | ||
2498 | drm_modeset_acquire_fini(&ctx); | ||
2499 | } | ||
2500 | EXPORT_SYMBOL(drm_atomic_helper_shutdown); | ||
2501 | |||
2502 | /** | ||
2520 | * drm_atomic_helper_suspend - subsystem-level suspend helper | 2503 | * drm_atomic_helper_suspend - subsystem-level suspend helper |
2521 | * @dev: DRM device | 2504 | * @dev: DRM device |
2522 | * | 2505 | * |
@@ -2862,6 +2845,7 @@ static int page_flip_common( | |||
2862 | * @fb: DRM framebuffer | 2845 | * @fb: DRM framebuffer |
2863 | * @event: optional DRM event to signal upon completion | 2846 | * @event: optional DRM event to signal upon completion |
2864 | * @flags: flip flags for non-vblank sync'ed updates | 2847 | * @flags: flip flags for non-vblank sync'ed updates |
2848 | * @ctx: lock acquisition context | ||
2865 | * | 2849 | * |
2866 | * Provides a default &drm_crtc_funcs.page_flip implementation | 2850 | * Provides a default &drm_crtc_funcs.page_flip implementation |
2867 | * using the atomic driver interface. | 2851 | * using the atomic driver interface. |
@@ -2875,7 +2859,8 @@ static int page_flip_common( | |||
2875 | int drm_atomic_helper_page_flip(struct drm_crtc *crtc, | 2859 | int drm_atomic_helper_page_flip(struct drm_crtc *crtc, |
2876 | struct drm_framebuffer *fb, | 2860 | struct drm_framebuffer *fb, |
2877 | struct drm_pending_vblank_event *event, | 2861 | struct drm_pending_vblank_event *event, |
2878 | uint32_t flags) | 2862 | uint32_t flags, |
2863 | struct drm_modeset_acquire_ctx *ctx) | ||
2879 | { | 2864 | { |
2880 | struct drm_plane *plane = crtc->primary; | 2865 | struct drm_plane *plane = crtc->primary; |
2881 | struct drm_atomic_state *state; | 2866 | struct drm_atomic_state *state; |
@@ -2885,34 +2870,16 @@ int drm_atomic_helper_page_flip(struct drm_crtc *crtc, | |||
2885 | if (!state) | 2870 | if (!state) |
2886 | return -ENOMEM; | 2871 | return -ENOMEM; |
2887 | 2872 | ||
2888 | state->acquire_ctx = drm_modeset_legacy_acquire_ctx(crtc); | 2873 | state->acquire_ctx = ctx; |
2889 | 2874 | ||
2890 | retry: | ||
2891 | ret = page_flip_common(state, crtc, fb, event, flags); | 2875 | ret = page_flip_common(state, crtc, fb, event, flags); |
2892 | if (ret != 0) | 2876 | if (ret != 0) |
2893 | goto fail; | 2877 | goto fail; |
2894 | 2878 | ||
2895 | ret = drm_atomic_nonblocking_commit(state); | 2879 | ret = drm_atomic_nonblocking_commit(state); |
2896 | |||
2897 | fail: | 2880 | fail: |
2898 | if (ret == -EDEADLK) | ||
2899 | goto backoff; | ||
2900 | |||
2901 | drm_atomic_state_put(state); | 2881 | drm_atomic_state_put(state); |
2902 | return ret; | 2882 | return ret; |
2903 | |||
2904 | backoff: | ||
2905 | drm_atomic_state_clear(state); | ||
2906 | drm_atomic_legacy_backoff(state); | ||
2907 | |||
2908 | /* | ||
2909 | * Someone might have exchanged the framebuffer while we dropped locks | ||
2910 | * in the backoff code. We need to fix up the fb refcount tracking the | ||
2911 | * core does for us. | ||
2912 | */ | ||
2913 | plane->old_fb = plane->fb; | ||
2914 | |||
2915 | goto retry; | ||
2916 | } | 2883 | } |
2917 | EXPORT_SYMBOL(drm_atomic_helper_page_flip); | 2884 | EXPORT_SYMBOL(drm_atomic_helper_page_flip); |
2918 | 2885 | ||
@@ -2923,6 +2890,7 @@ EXPORT_SYMBOL(drm_atomic_helper_page_flip); | |||
2923 | * @event: optional DRM event to signal upon completion | 2890 | * @event: optional DRM event to signal upon completion |
2924 | * @flags: flip flags for non-vblank sync'ed updates | 2891 | * @flags: flip flags for non-vblank sync'ed updates |
2925 | * @target: specifying the target vblank period when the flip to take effect | 2892 | * @target: specifying the target vblank period when the flip to take effect |
2893 | * @ctx: lock acquisition context | ||
2926 | * | 2894 | * |
2927 | * Provides a default &drm_crtc_funcs.page_flip_target implementation. | 2895 | * Provides a default &drm_crtc_funcs.page_flip_target implementation. |
2928 | * Similar to drm_atomic_helper_page_flip() with extra parameter to specify | 2896 | * Similar to drm_atomic_helper_page_flip() with extra parameter to specify |
@@ -2936,7 +2904,8 @@ int drm_atomic_helper_page_flip_target( | |||
2936 | struct drm_framebuffer *fb, | 2904 | struct drm_framebuffer *fb, |
2937 | struct drm_pending_vblank_event *event, | 2905 | struct drm_pending_vblank_event *event, |
2938 | uint32_t flags, | 2906 | uint32_t flags, |
2939 | uint32_t target) | 2907 | uint32_t target, |
2908 | struct drm_modeset_acquire_ctx *ctx) | ||
2940 | { | 2909 | { |
2941 | struct drm_plane *plane = crtc->primary; | 2910 | struct drm_plane *plane = crtc->primary; |
2942 | struct drm_atomic_state *state; | 2911 | struct drm_atomic_state *state; |
@@ -2947,9 +2916,8 @@ int drm_atomic_helper_page_flip_target( | |||
2947 | if (!state) | 2916 | if (!state) |
2948 | return -ENOMEM; | 2917 | return -ENOMEM; |
2949 | 2918 | ||
2950 | state->acquire_ctx = drm_modeset_legacy_acquire_ctx(crtc); | 2919 | state->acquire_ctx = ctx; |
2951 | 2920 | ||
2952 | retry: | ||
2953 | ret = page_flip_common(state, crtc, fb, event, flags); | 2921 | ret = page_flip_common(state, crtc, fb, event, flags); |
2954 | if (ret != 0) | 2922 | if (ret != 0) |
2955 | goto fail; | 2923 | goto fail; |
@@ -2962,26 +2930,9 @@ retry: | |||
2962 | crtc_state->target_vblank = target; | 2930 | crtc_state->target_vblank = target; |
2963 | 2931 | ||
2964 | ret = drm_atomic_nonblocking_commit(state); | 2932 | ret = drm_atomic_nonblocking_commit(state); |
2965 | |||
2966 | fail: | 2933 | fail: |
2967 | if (ret == -EDEADLK) | ||
2968 | goto backoff; | ||
2969 | |||
2970 | drm_atomic_state_put(state); | 2934 | drm_atomic_state_put(state); |
2971 | return ret; | 2935 | return ret; |
2972 | |||
2973 | backoff: | ||
2974 | drm_atomic_state_clear(state); | ||
2975 | drm_atomic_legacy_backoff(state); | ||
2976 | |||
2977 | /* | ||
2978 | * Someone might have exchanged the framebuffer while we dropped locks | ||
2979 | * in the backoff code. We need to fix up the fb refcount tracking the | ||
2980 | * core does for us. | ||
2981 | */ | ||
2982 | plane->old_fb = plane->fb; | ||
2983 | |||
2984 | goto retry; | ||
2985 | } | 2936 | } |
2986 | EXPORT_SYMBOL(drm_atomic_helper_page_flip_target); | 2937 | EXPORT_SYMBOL(drm_atomic_helper_page_flip_target); |
2987 | 2938 | ||
diff --git a/drivers/gpu/drm/drm_crtc.c b/drivers/gpu/drm/drm_crtc.c index e2974d3c92e7..d69e180fc563 100644 --- a/drivers/gpu/drm/drm_crtc.c +++ b/drivers/gpu/drm/drm_crtc.c | |||
@@ -94,6 +94,8 @@ EXPORT_SYMBOL(drm_crtc_from_index); | |||
94 | * drm_crtc_force_disable - Forcibly turn off a CRTC | 94 | * drm_crtc_force_disable - Forcibly turn off a CRTC |
95 | * @crtc: CRTC to turn off | 95 | * @crtc: CRTC to turn off |
96 | * | 96 | * |
97 | * Note: This should only be used by non-atomic legacy drivers. | ||
98 | * | ||
97 | * Returns: | 99 | * Returns: |
98 | * Zero on success, error code on failure. | 100 | * Zero on success, error code on failure. |
99 | */ | 101 | */ |
@@ -103,6 +105,8 @@ int drm_crtc_force_disable(struct drm_crtc *crtc) | |||
103 | .crtc = crtc, | 105 | .crtc = crtc, |
104 | }; | 106 | }; |
105 | 107 | ||
108 | WARN_ON(drm_drv_uses_atomic_modeset(crtc->dev)); | ||
109 | |||
106 | return drm_mode_set_config_internal(&set); | 110 | return drm_mode_set_config_internal(&set); |
107 | } | 111 | } |
108 | EXPORT_SYMBOL(drm_crtc_force_disable); | 112 | EXPORT_SYMBOL(drm_crtc_force_disable); |
@@ -114,6 +118,9 @@ EXPORT_SYMBOL(drm_crtc_force_disable); | |||
114 | * Drivers may want to call this on unload to ensure that all displays are | 118 | * Drivers may want to call this on unload to ensure that all displays are |
115 | * unlit and the GPU is in a consistent, low power state. Takes modeset locks. | 119 | * unlit and the GPU is in a consistent, low power state. Takes modeset locks. |
116 | * | 120 | * |
121 | * Note: This should only be used by non-atomic legacy drivers. For an atomic | ||
122 | * version look at drm_atomic_helper_shutdown(). | ||
123 | * | ||
117 | * Returns: | 124 | * Returns: |
118 | * Zero on success, error code on failure. | 125 | * Zero on success, error code on failure. |
119 | */ | 126 | */ |
@@ -399,9 +406,9 @@ int drm_mode_getcrtc(struct drm_device *dev, | |||
399 | if (!crtc) | 406 | if (!crtc) |
400 | return -ENOENT; | 407 | return -ENOENT; |
401 | 408 | ||
402 | drm_modeset_lock_crtc(crtc, crtc->primary); | ||
403 | crtc_resp->gamma_size = crtc->gamma_size; | 409 | crtc_resp->gamma_size = crtc->gamma_size; |
404 | 410 | ||
411 | drm_modeset_lock(&crtc->primary->mutex, NULL); | ||
405 | if (crtc->primary->state && crtc->primary->state->fb) | 412 | if (crtc->primary->state && crtc->primary->state->fb) |
406 | crtc_resp->fb_id = crtc->primary->state->fb->base.id; | 413 | crtc_resp->fb_id = crtc->primary->state->fb->base.id; |
407 | else if (!crtc->primary->state && crtc->primary->fb) | 414 | else if (!crtc->primary->state && crtc->primary->fb) |
@@ -409,9 +416,14 @@ int drm_mode_getcrtc(struct drm_device *dev, | |||
409 | else | 416 | else |
410 | crtc_resp->fb_id = 0; | 417 | crtc_resp->fb_id = 0; |
411 | 418 | ||
412 | if (crtc->state) { | 419 | if (crtc->primary->state) { |
413 | crtc_resp->x = crtc->primary->state->src_x >> 16; | 420 | crtc_resp->x = crtc->primary->state->src_x >> 16; |
414 | crtc_resp->y = crtc->primary->state->src_y >> 16; | 421 | crtc_resp->y = crtc->primary->state->src_y >> 16; |
422 | } | ||
423 | drm_modeset_unlock(&crtc->primary->mutex); | ||
424 | |||
425 | drm_modeset_lock(&crtc->mutex, NULL); | ||
426 | if (crtc->state) { | ||
415 | if (crtc->state->enable) { | 427 | if (crtc->state->enable) { |
416 | drm_mode_convert_to_umode(&crtc_resp->mode, &crtc->state->mode); | 428 | drm_mode_convert_to_umode(&crtc_resp->mode, &crtc->state->mode); |
417 | crtc_resp->mode_valid = 1; | 429 | crtc_resp->mode_valid = 1; |
@@ -430,23 +442,13 @@ int drm_mode_getcrtc(struct drm_device *dev, | |||
430 | crtc_resp->mode_valid = 0; | 442 | crtc_resp->mode_valid = 0; |
431 | } | 443 | } |
432 | } | 444 | } |
433 | drm_modeset_unlock_crtc(crtc); | 445 | drm_modeset_unlock(&crtc->mutex); |
434 | 446 | ||
435 | return 0; | 447 | return 0; |
436 | } | 448 | } |
437 | 449 | ||
438 | /** | 450 | static int __drm_mode_set_config_internal(struct drm_mode_set *set, |
439 | * drm_mode_set_config_internal - helper to call &drm_mode_config_funcs.set_config | 451 | struct drm_modeset_acquire_ctx *ctx) |
440 | * @set: modeset config to set | ||
441 | * | ||
442 | * This is a little helper to wrap internal calls to the | ||
443 | * &drm_mode_config_funcs.set_config driver interface. The only thing it adds is | ||
444 | * correct refcounting dance. | ||
445 | * | ||
446 | * Returns: | ||
447 | * Zero on success, negative errno on failure. | ||
448 | */ | ||
449 | int drm_mode_set_config_internal(struct drm_mode_set *set) | ||
450 | { | 452 | { |
451 | struct drm_crtc *crtc = set->crtc; | 453 | struct drm_crtc *crtc = set->crtc; |
452 | struct drm_framebuffer *fb; | 454 | struct drm_framebuffer *fb; |
@@ -463,7 +465,7 @@ int drm_mode_set_config_internal(struct drm_mode_set *set) | |||
463 | 465 | ||
464 | fb = set->fb; | 466 | fb = set->fb; |
465 | 467 | ||
466 | ret = crtc->funcs->set_config(set); | 468 | ret = crtc->funcs->set_config(set, ctx); |
467 | if (ret == 0) { | 469 | if (ret == 0) { |
468 | crtc->primary->crtc = crtc; | 470 | crtc->primary->crtc = crtc; |
469 | crtc->primary->fb = fb; | 471 | crtc->primary->fb = fb; |
@@ -479,6 +481,25 @@ int drm_mode_set_config_internal(struct drm_mode_set *set) | |||
479 | 481 | ||
480 | return ret; | 482 | return ret; |
481 | } | 483 | } |
484 | /** | ||
485 | * drm_mode_set_config_internal - helper to call &drm_mode_config_funcs.set_config | ||
486 | * @set: modeset config to set | ||
487 | * | ||
488 | * This is a little helper to wrap internal calls to the | ||
489 | * &drm_mode_config_funcs.set_config driver interface. The only thing it adds is | ||
490 | * correct refcounting dance. | ||
491 | * | ||
492 | * This should only be used by non-atomic legacy drivers. | ||
493 | * | ||
494 | * Returns: | ||
495 | * Zero on success, negative errno on failure. | ||
496 | */ | ||
497 | int drm_mode_set_config_internal(struct drm_mode_set *set) | ||
498 | { | ||
499 | WARN_ON(drm_drv_uses_atomic_modeset(set->crtc->dev)); | ||
500 | |||
501 | return __drm_mode_set_config_internal(set, NULL); | ||
502 | } | ||
482 | EXPORT_SYMBOL(drm_mode_set_config_internal); | 503 | EXPORT_SYMBOL(drm_mode_set_config_internal); |
483 | 504 | ||
484 | /** | 505 | /** |
@@ -534,6 +555,7 @@ int drm_mode_setcrtc(struct drm_device *dev, void *data, | |||
534 | struct drm_display_mode *mode = NULL; | 555 | struct drm_display_mode *mode = NULL; |
535 | struct drm_mode_set set; | 556 | struct drm_mode_set set; |
536 | uint32_t __user *set_connectors_ptr; | 557 | uint32_t __user *set_connectors_ptr; |
558 | struct drm_modeset_acquire_ctx ctx; | ||
537 | int ret; | 559 | int ret; |
538 | int i; | 560 | int i; |
539 | 561 | ||
@@ -547,15 +569,18 @@ int drm_mode_setcrtc(struct drm_device *dev, void *data, | |||
547 | if (crtc_req->x & 0xffff0000 || crtc_req->y & 0xffff0000) | 569 | if (crtc_req->x & 0xffff0000 || crtc_req->y & 0xffff0000) |
548 | return -ERANGE; | 570 | return -ERANGE; |
549 | 571 | ||
550 | drm_modeset_lock_all(dev); | ||
551 | crtc = drm_crtc_find(dev, crtc_req->crtc_id); | 572 | crtc = drm_crtc_find(dev, crtc_req->crtc_id); |
552 | if (!crtc) { | 573 | if (!crtc) { |
553 | DRM_DEBUG_KMS("Unknown CRTC ID %d\n", crtc_req->crtc_id); | 574 | DRM_DEBUG_KMS("Unknown CRTC ID %d\n", crtc_req->crtc_id); |
554 | ret = -ENOENT; | 575 | return -ENOENT; |
555 | goto out; | ||
556 | } | 576 | } |
557 | DRM_DEBUG_KMS("[CRTC:%d:%s]\n", crtc->base.id, crtc->name); | 577 | DRM_DEBUG_KMS("[CRTC:%d:%s]\n", crtc->base.id, crtc->name); |
558 | 578 | ||
579 | drm_modeset_acquire_init(&ctx, 0); | ||
580 | retry: | ||
581 | ret = drm_modeset_lock_all_ctx(crtc->dev, &ctx); | ||
582 | if (ret) | ||
583 | goto out; | ||
559 | if (crtc_req->mode_valid) { | 584 | if (crtc_req->mode_valid) { |
560 | /* If we have a mode we need a framebuffer. */ | 585 | /* If we have a mode we need a framebuffer. */ |
561 | /* If we pass -1, set the mode with the currently bound fb */ | 586 | /* If we pass -1, set the mode with the currently bound fb */ |
@@ -676,7 +701,7 @@ int drm_mode_setcrtc(struct drm_device *dev, void *data, | |||
676 | set.connectors = connector_set; | 701 | set.connectors = connector_set; |
677 | set.num_connectors = crtc_req->count_connectors; | 702 | set.num_connectors = crtc_req->count_connectors; |
678 | set.fb = fb; | 703 | set.fb = fb; |
679 | ret = drm_mode_set_config_internal(&set); | 704 | ret = __drm_mode_set_config_internal(&set, &ctx); |
680 | 705 | ||
681 | out: | 706 | out: |
682 | if (fb) | 707 | if (fb) |
@@ -690,7 +715,13 @@ out: | |||
690 | } | 715 | } |
691 | kfree(connector_set); | 716 | kfree(connector_set); |
692 | drm_mode_destroy(dev, mode); | 717 | drm_mode_destroy(dev, mode); |
693 | drm_modeset_unlock_all(dev); | 718 | if (ret == -EDEADLK) { |
719 | drm_modeset_backoff(&ctx); | ||
720 | goto retry; | ||
721 | } | ||
722 | drm_modeset_drop_locks(&ctx); | ||
723 | drm_modeset_acquire_fini(&ctx); | ||
724 | |||
694 | return ret; | 725 | return ret; |
695 | } | 726 | } |
696 | 727 | ||
diff --git a/drivers/gpu/drm/drm_crtc_helper.c b/drivers/gpu/drm/drm_crtc_helper.c index 8aa8c1084121..4afdf7902eda 100644 --- a/drivers/gpu/drm/drm_crtc_helper.c +++ b/drivers/gpu/drm/drm_crtc_helper.c | |||
@@ -476,6 +476,7 @@ drm_crtc_helper_disable(struct drm_crtc *crtc) | |||
476 | /** | 476 | /** |
477 | * drm_crtc_helper_set_config - set a new config from userspace | 477 | * drm_crtc_helper_set_config - set a new config from userspace |
478 | * @set: mode set configuration | 478 | * @set: mode set configuration |
479 | * @ctx: lock acquire context, not used here | ||
479 | * | 480 | * |
480 | * The drm_crtc_helper_set_config() helper function implements the of | 481 | * The drm_crtc_helper_set_config() helper function implements the of |
481 | * &drm_crtc_funcs.set_config callback for drivers using the legacy CRTC | 482 | * &drm_crtc_funcs.set_config callback for drivers using the legacy CRTC |
@@ -510,7 +511,8 @@ drm_crtc_helper_disable(struct drm_crtc *crtc) | |||
510 | * Returns: | 511 | * Returns: |
511 | * Returns 0 on success, negative errno numbers on failure. | 512 | * Returns 0 on success, negative errno numbers on failure. |
512 | */ | 513 | */ |
513 | int drm_crtc_helper_set_config(struct drm_mode_set *set) | 514 | int drm_crtc_helper_set_config(struct drm_mode_set *set, |
515 | struct drm_modeset_acquire_ctx *ctx) | ||
514 | { | 516 | { |
515 | struct drm_device *dev; | 517 | struct drm_device *dev; |
516 | struct drm_crtc **save_encoder_crtcs, *new_crtc; | 518 | struct drm_crtc **save_encoder_crtcs, *new_crtc; |
diff --git a/drivers/gpu/drm/drm_debugfs.c b/drivers/gpu/drm/drm_debugfs.c index 1d2d18d82d2e..c1807d5754b2 100644 --- a/drivers/gpu/drm/drm_debugfs.c +++ b/drivers/gpu/drm/drm_debugfs.c | |||
@@ -1,10 +1,3 @@ | |||
1 | /** | ||
2 | * \file drm_debugfs.c | ||
3 | * debugfs support for DRM | ||
4 | * | ||
5 | * \author Ben Gamari <bgamari@gmail.com> | ||
6 | */ | ||
7 | |||
8 | /* | 1 | /* |
9 | * Created: Sun Dec 21 13:08:50 2008 by bgamari@gmail.com | 2 | * Created: Sun Dec 21 13:08:50 2008 by bgamari@gmail.com |
10 | * | 3 | * |
@@ -34,9 +27,12 @@ | |||
34 | #include <linux/seq_file.h> | 27 | #include <linux/seq_file.h> |
35 | #include <linux/slab.h> | 28 | #include <linux/slab.h> |
36 | #include <linux/export.h> | 29 | #include <linux/export.h> |
37 | #include <drm/drmP.h> | 30 | |
31 | #include <drm/drm_debugfs.h> | ||
38 | #include <drm/drm_edid.h> | 32 | #include <drm/drm_edid.h> |
39 | #include <drm/drm_atomic.h> | 33 | #include <drm/drm_atomic.h> |
34 | #include <drm/drmP.h> | ||
35 | |||
40 | #include "drm_internal.h" | 36 | #include "drm_internal.h" |
41 | #include "drm_crtc_internal.h" | 37 | #include "drm_crtc_internal.h" |
42 | 38 | ||
@@ -72,16 +68,15 @@ static const struct file_operations drm_debugfs_fops = { | |||
72 | 68 | ||
73 | 69 | ||
74 | /** | 70 | /** |
75 | * Initialize a given set of debugfs files for a device | 71 | * drm_debugfs_create_files - Initialize a given set of debugfs files for DRM |
76 | * | 72 | * minor |
77 | * \param files The array of files to create | 73 | * @files: The array of files to create |
78 | * \param count The number of files given | 74 | * @count: The number of files given |
79 | * \param root DRI debugfs dir entry. | 75 | * @root: DRI debugfs dir entry. |
80 | * \param minor device minor number | 76 | * @minor: device minor number |
81 | * \return Zero on success, non-zero on failure | ||
82 | * | 77 | * |
83 | * Create a given set of debugfs files represented by an array of | 78 | * Create a given set of debugfs files represented by an array of |
84 | * &drm_info_list in the given root directory. These files will be removed | 79 | * &struct drm_info_list in the given root directory. These files will be removed |
85 | * automatically on drm_debugfs_cleanup(). | 80 | * automatically on drm_debugfs_cleanup(). |
86 | */ | 81 | */ |
87 | int drm_debugfs_create_files(const struct drm_info_list *files, int count, | 82 | int drm_debugfs_create_files(const struct drm_info_list *files, int count, |
@@ -130,17 +125,6 @@ fail: | |||
130 | } | 125 | } |
131 | EXPORT_SYMBOL(drm_debugfs_create_files); | 126 | EXPORT_SYMBOL(drm_debugfs_create_files); |
132 | 127 | ||
133 | /** | ||
134 | * Initialize the DRI debugfs filesystem for a device | ||
135 | * | ||
136 | * \param dev DRM device | ||
137 | * \param minor device minor number | ||
138 | * \param root DRI debugfs dir entry. | ||
139 | * | ||
140 | * Create the DRI debugfs root entry "/sys/kernel/debug/dri", the device debugfs root entry | ||
141 | * "/sys/kernel/debug/dri/%minor%/", and each entry in debugfs_list as | ||
142 | * "/sys/kernel/debug/dri/%minor%/%name%". | ||
143 | */ | ||
144 | int drm_debugfs_init(struct drm_minor *minor, int minor_id, | 128 | int drm_debugfs_init(struct drm_minor *minor, int minor_id, |
145 | struct dentry *root) | 129 | struct dentry *root) |
146 | { | 130 | { |
@@ -186,16 +170,6 @@ int drm_debugfs_init(struct drm_minor *minor, int minor_id, | |||
186 | } | 170 | } |
187 | 171 | ||
188 | 172 | ||
189 | /** | ||
190 | * Remove a list of debugfs files | ||
191 | * | ||
192 | * \param files The list of files | ||
193 | * \param count The number of files | ||
194 | * \param minor The minor of which we should remove the files | ||
195 | * \return always zero. | ||
196 | * | ||
197 | * Remove all debugfs entries created by debugfs_init(). | ||
198 | */ | ||
199 | int drm_debugfs_remove_files(const struct drm_info_list *files, int count, | 173 | int drm_debugfs_remove_files(const struct drm_info_list *files, int count, |
200 | struct drm_minor *minor) | 174 | struct drm_minor *minor) |
201 | { | 175 | { |
@@ -232,14 +206,6 @@ static void drm_debugfs_remove_all_files(struct drm_minor *minor) | |||
232 | mutex_unlock(&minor->debugfs_lock); | 206 | mutex_unlock(&minor->debugfs_lock); |
233 | } | 207 | } |
234 | 208 | ||
235 | /** | ||
236 | * Cleanup the debugfs filesystem resources. | ||
237 | * | ||
238 | * \param minor device minor number. | ||
239 | * \return always zero. | ||
240 | * | ||
241 | * Remove all debugfs entries created by debugfs_init(). | ||
242 | */ | ||
243 | int drm_debugfs_cleanup(struct drm_minor *minor) | 209 | int drm_debugfs_cleanup(struct drm_minor *minor) |
244 | { | 210 | { |
245 | if (!minor->debugfs_root) | 211 | if (!minor->debugfs_root) |
diff --git a/drivers/gpu/drm/drm_debugfs_crc.c b/drivers/gpu/drm/drm_debugfs_crc.c index 96891c4a6e23..1722d8f21449 100644 --- a/drivers/gpu/drm/drm_debugfs_crc.c +++ b/drivers/gpu/drm/drm_debugfs_crc.c | |||
@@ -36,7 +36,7 @@ | |||
36 | * DOC: CRC ABI | 36 | * DOC: CRC ABI |
37 | * | 37 | * |
38 | * DRM device drivers can provide to userspace CRC information of each frame as | 38 | * DRM device drivers can provide to userspace CRC information of each frame as |
39 | * it reached a given hardware component (a "source"). | 39 | * it reached a given hardware component (a CRC sampling "source"). |
40 | * | 40 | * |
41 | * Userspace can control generation of CRCs in a given CRTC by writing to the | 41 | * Userspace can control generation of CRCs in a given CRTC by writing to the |
42 | * file dri/0/crtc-N/crc/control in debugfs, with N being the index of the CRTC. | 42 | * file dri/0/crtc-N/crc/control in debugfs, with N being the index of the CRTC. |
@@ -57,6 +57,11 @@ | |||
57 | * rely on being able to generate matching CRC values for the frame contents that | 57 | * rely on being able to generate matching CRC values for the frame contents that |
58 | * it submits. In this general case, the maximum userspace can do is to compare | 58 | * it submits. In this general case, the maximum userspace can do is to compare |
59 | * the reported CRCs of frames that should have the same contents. | 59 | * the reported CRCs of frames that should have the same contents. |
60 | * | ||
61 | * On the driver side the implementation effort is minimal, drivers only need to | ||
62 | * implement &drm_crtc_funcs.set_crc_source. The debugfs files are automatically | ||
63 | * set up if that vfunc is set. CRC samples need to be captured in the driver by | ||
64 | * calling drm_crtc_add_crc_entry(). | ||
60 | */ | 65 | */ |
61 | 66 | ||
62 | static int crc_control_show(struct seq_file *m, void *data) | 67 | static int crc_control_show(struct seq_file *m, void *data) |
@@ -280,16 +285,6 @@ static const struct file_operations drm_crtc_crc_data_fops = { | |||
280 | .release = crtc_crc_release, | 285 | .release = crtc_crc_release, |
281 | }; | 286 | }; |
282 | 287 | ||
283 | /** | ||
284 | * drm_debugfs_crtc_crc_add - Add files to debugfs for capture of frame CRCs | ||
285 | * @crtc: CRTC to whom the frames will belong | ||
286 | * | ||
287 | * Adds files to debugfs directory that allows userspace to control the | ||
288 | * generation of frame CRCs and to read them. | ||
289 | * | ||
290 | * Returns: | ||
291 | * Zero on success, error code on failure. | ||
292 | */ | ||
293 | int drm_debugfs_crtc_crc_add(struct drm_crtc *crtc) | 288 | int drm_debugfs_crtc_crc_add(struct drm_crtc *crtc) |
294 | { | 289 | { |
295 | struct dentry *crc_ent, *ent; | 290 | struct dentry *crc_ent, *ent; |
diff --git a/drivers/gpu/drm/drm_dp_mst_topology.c b/drivers/gpu/drm/drm_dp_mst_topology.c index f2cc375907d0..d3fc7e4e85b7 100644 --- a/drivers/gpu/drm/drm_dp_mst_topology.c +++ b/drivers/gpu/drm/drm_dp_mst_topology.c | |||
@@ -2042,10 +2042,6 @@ int drm_dp_mst_topology_mgr_set_mst(struct drm_dp_mst_topology_mgr *mgr, bool ms | |||
2042 | goto out_unlock; | 2042 | goto out_unlock; |
2043 | } | 2043 | } |
2044 | 2044 | ||
2045 | mgr->total_pbn = 2560; | ||
2046 | mgr->total_slots = DIV_ROUND_UP(mgr->total_pbn, mgr->pbn_div); | ||
2047 | mgr->avail_slots = mgr->total_slots; | ||
2048 | |||
2049 | /* add initial branch device at LCT 1 */ | 2045 | /* add initial branch device at LCT 1 */ |
2050 | mstb = drm_dp_add_mst_branch_device(1, NULL); | 2046 | mstb = drm_dp_add_mst_branch_device(1, NULL); |
2051 | if (mstb == NULL) { | 2047 | if (mstb == NULL) { |
@@ -2475,26 +2471,25 @@ int drm_dp_find_vcpi_slots(struct drm_dp_mst_topology_mgr *mgr, | |||
2475 | 2471 | ||
2476 | num_slots = DIV_ROUND_UP(pbn, mgr->pbn_div); | 2472 | num_slots = DIV_ROUND_UP(pbn, mgr->pbn_div); |
2477 | 2473 | ||
2478 | if (num_slots > mgr->avail_slots) | 2474 | /* max. time slots - one slot for MTP header */ |
2475 | if (num_slots > 63) | ||
2479 | return -ENOSPC; | 2476 | return -ENOSPC; |
2480 | return num_slots; | 2477 | return num_slots; |
2481 | } | 2478 | } |
2482 | EXPORT_SYMBOL(drm_dp_find_vcpi_slots); | 2479 | EXPORT_SYMBOL(drm_dp_find_vcpi_slots); |
2483 | 2480 | ||
2484 | static int drm_dp_init_vcpi(struct drm_dp_mst_topology_mgr *mgr, | 2481 | static int drm_dp_init_vcpi(struct drm_dp_mst_topology_mgr *mgr, |
2485 | struct drm_dp_vcpi *vcpi, int pbn) | 2482 | struct drm_dp_vcpi *vcpi, int pbn, int slots) |
2486 | { | 2483 | { |
2487 | int num_slots; | ||
2488 | int ret; | 2484 | int ret; |
2489 | 2485 | ||
2490 | num_slots = DIV_ROUND_UP(pbn, mgr->pbn_div); | 2486 | /* max. time slots - one slot for MTP header */ |
2491 | 2487 | if (slots > 63) | |
2492 | if (num_slots > mgr->avail_slots) | ||
2493 | return -ENOSPC; | 2488 | return -ENOSPC; |
2494 | 2489 | ||
2495 | vcpi->pbn = pbn; | 2490 | vcpi->pbn = pbn; |
2496 | vcpi->aligned_pbn = num_slots * mgr->pbn_div; | 2491 | vcpi->aligned_pbn = slots * mgr->pbn_div; |
2497 | vcpi->num_slots = num_slots; | 2492 | vcpi->num_slots = slots; |
2498 | 2493 | ||
2499 | ret = drm_dp_mst_assign_payload_id(mgr, vcpi); | 2494 | ret = drm_dp_mst_assign_payload_id(mgr, vcpi); |
2500 | if (ret < 0) | 2495 | if (ret < 0) |
@@ -2509,7 +2504,8 @@ static int drm_dp_init_vcpi(struct drm_dp_mst_topology_mgr *mgr, | |||
2509 | * @pbn: payload bandwidth number to request | 2504 | * @pbn: payload bandwidth number to request |
2510 | * @slots: returned number of slots for this PBN. | 2505 | * @slots: returned number of slots for this PBN. |
2511 | */ | 2506 | */ |
2512 | bool drm_dp_mst_allocate_vcpi(struct drm_dp_mst_topology_mgr *mgr, struct drm_dp_mst_port *port, int pbn, int *slots) | 2507 | bool drm_dp_mst_allocate_vcpi(struct drm_dp_mst_topology_mgr *mgr, |
2508 | struct drm_dp_mst_port *port, int pbn, int slots) | ||
2513 | { | 2509 | { |
2514 | int ret; | 2510 | int ret; |
2515 | 2511 | ||
@@ -2517,22 +2513,25 @@ bool drm_dp_mst_allocate_vcpi(struct drm_dp_mst_topology_mgr *mgr, struct drm_dp | |||
2517 | if (!port) | 2513 | if (!port) |
2518 | return false; | 2514 | return false; |
2519 | 2515 | ||
2516 | if (slots < 0) | ||
2517 | return false; | ||
2518 | |||
2520 | if (port->vcpi.vcpi > 0) { | 2519 | if (port->vcpi.vcpi > 0) { |
2521 | DRM_DEBUG_KMS("payload: vcpi %d already allocated for pbn %d - requested pbn %d\n", port->vcpi.vcpi, port->vcpi.pbn, pbn); | 2520 | DRM_DEBUG_KMS("payload: vcpi %d already allocated for pbn %d - requested pbn %d\n", port->vcpi.vcpi, port->vcpi.pbn, pbn); |
2522 | if (pbn == port->vcpi.pbn) { | 2521 | if (pbn == port->vcpi.pbn) { |
2523 | *slots = port->vcpi.num_slots; | ||
2524 | drm_dp_put_port(port); | 2522 | drm_dp_put_port(port); |
2525 | return true; | 2523 | return true; |
2526 | } | 2524 | } |
2527 | } | 2525 | } |
2528 | 2526 | ||
2529 | ret = drm_dp_init_vcpi(mgr, &port->vcpi, pbn); | 2527 | ret = drm_dp_init_vcpi(mgr, &port->vcpi, pbn, slots); |
2530 | if (ret) { | 2528 | if (ret) { |
2531 | DRM_DEBUG_KMS("failed to init vcpi %d %d %d\n", DIV_ROUND_UP(pbn, mgr->pbn_div), mgr->avail_slots, ret); | 2529 | DRM_DEBUG_KMS("failed to init vcpi slots=%d max=63 ret=%d\n", |
2530 | DIV_ROUND_UP(pbn, mgr->pbn_div), ret); | ||
2532 | goto out; | 2531 | goto out; |
2533 | } | 2532 | } |
2534 | DRM_DEBUG_KMS("initing vcpi for %d %d\n", pbn, port->vcpi.num_slots); | 2533 | DRM_DEBUG_KMS("initing vcpi for pbn=%d slots=%d\n", |
2535 | *slots = port->vcpi.num_slots; | 2534 | pbn, port->vcpi.num_slots); |
2536 | 2535 | ||
2537 | drm_dp_put_port(port); | 2536 | drm_dp_put_port(port); |
2538 | return true; | 2537 | return true; |
diff --git a/drivers/gpu/drm/drm_fb_cma_helper.c b/drivers/gpu/drm/drm_fb_cma_helper.c index 74cd393a6407..50abd1faf38f 100644 --- a/drivers/gpu/drm/drm_fb_cma_helper.c +++ b/drivers/gpu/drm/drm_fb_cma_helper.c | |||
@@ -177,7 +177,7 @@ struct drm_framebuffer *drm_fb_cma_create_with_funcs(struct drm_device *dev, | |||
177 | int ret; | 177 | int ret; |
178 | int i; | 178 | int i; |
179 | 179 | ||
180 | info = drm_format_info(mode_cmd->pixel_format); | 180 | info = drm_get_format_info(dev, mode_cmd); |
181 | if (!info) | 181 | if (!info) |
182 | return ERR_PTR(-EINVAL); | 182 | return ERR_PTR(-EINVAL); |
183 | 183 | ||
diff --git a/drivers/gpu/drm/drm_fourcc.c b/drivers/gpu/drm/drm_fourcc.c index 92bf3306d4b3..9c0152df45ad 100644 --- a/drivers/gpu/drm/drm_fourcc.c +++ b/drivers/gpu/drm/drm_fourcc.c | |||
@@ -207,6 +207,31 @@ const struct drm_format_info *drm_format_info(u32 format) | |||
207 | EXPORT_SYMBOL(drm_format_info); | 207 | EXPORT_SYMBOL(drm_format_info); |
208 | 208 | ||
209 | /** | 209 | /** |
210 | * drm_get_format_info - query information for a given framebuffer configuration | ||
211 | * @dev: DRM device | ||
212 | * @mode_cmd: metadata from the userspace fb creation request | ||
213 | * | ||
214 | * Returns: | ||
215 | * The instance of struct drm_format_info that describes the pixel format, or | ||
216 | * NULL if the format is unsupported. | ||
217 | */ | ||
218 | const struct drm_format_info * | ||
219 | drm_get_format_info(struct drm_device *dev, | ||
220 | const struct drm_mode_fb_cmd2 *mode_cmd) | ||
221 | { | ||
222 | const struct drm_format_info *info = NULL; | ||
223 | |||
224 | if (dev->mode_config.funcs->get_format_info) | ||
225 | info = dev->mode_config.funcs->get_format_info(mode_cmd); | ||
226 | |||
227 | if (!info) | ||
228 | info = drm_format_info(mode_cmd->pixel_format); | ||
229 | |||
230 | return info; | ||
231 | } | ||
232 | EXPORT_SYMBOL(drm_get_format_info); | ||
233 | |||
234 | /** | ||
210 | * drm_format_num_planes - get the number of planes for format | 235 | * drm_format_num_planes - get the number of planes for format |
211 | * @format: pixel format (DRM_FORMAT_*) | 236 | * @format: pixel format (DRM_FORMAT_*) |
212 | * | 237 | * |
diff --git a/drivers/gpu/drm/drm_framebuffer.c b/drivers/gpu/drm/drm_framebuffer.c index e4909aef75d7..e8f9c13a0afd 100644 --- a/drivers/gpu/drm/drm_framebuffer.c +++ b/drivers/gpu/drm/drm_framebuffer.c | |||
@@ -126,11 +126,31 @@ int drm_mode_addfb(struct drm_device *dev, | |||
126 | return 0; | 126 | return 0; |
127 | } | 127 | } |
128 | 128 | ||
129 | static int framebuffer_check(const struct drm_mode_fb_cmd2 *r) | 129 | static int fb_plane_width(int width, |
130 | const struct drm_format_info *format, int plane) | ||
131 | { | ||
132 | if (plane == 0) | ||
133 | return width; | ||
134 | |||
135 | return DIV_ROUND_UP(width, format->hsub); | ||
136 | } | ||
137 | |||
138 | static int fb_plane_height(int height, | ||
139 | const struct drm_format_info *format, int plane) | ||
140 | { | ||
141 | if (plane == 0) | ||
142 | return height; | ||
143 | |||
144 | return DIV_ROUND_UP(height, format->vsub); | ||
145 | } | ||
146 | |||
147 | static int framebuffer_check(struct drm_device *dev, | ||
148 | const struct drm_mode_fb_cmd2 *r) | ||
130 | { | 149 | { |
131 | const struct drm_format_info *info; | 150 | const struct drm_format_info *info; |
132 | int i; | 151 | int i; |
133 | 152 | ||
153 | /* check if the format is supported at all */ | ||
134 | info = __drm_format_info(r->pixel_format & ~DRM_FORMAT_BIG_ENDIAN); | 154 | info = __drm_format_info(r->pixel_format & ~DRM_FORMAT_BIG_ENDIAN); |
135 | if (!info) { | 155 | if (!info) { |
136 | struct drm_format_name_buf format_name; | 156 | struct drm_format_name_buf format_name; |
@@ -140,19 +160,22 @@ static int framebuffer_check(const struct drm_mode_fb_cmd2 *r) | |||
140 | return -EINVAL; | 160 | return -EINVAL; |
141 | } | 161 | } |
142 | 162 | ||
143 | if (r->width == 0 || r->width % info->hsub) { | 163 | /* now let the driver pick its own format info */ |
164 | info = drm_get_format_info(dev, r); | ||
165 | |||
166 | if (r->width == 0) { | ||
144 | DRM_DEBUG_KMS("bad framebuffer width %u\n", r->width); | 167 | DRM_DEBUG_KMS("bad framebuffer width %u\n", r->width); |
145 | return -EINVAL; | 168 | return -EINVAL; |
146 | } | 169 | } |
147 | 170 | ||
148 | if (r->height == 0 || r->height % info->vsub) { | 171 | if (r->height == 0) { |
149 | DRM_DEBUG_KMS("bad framebuffer height %u\n", r->height); | 172 | DRM_DEBUG_KMS("bad framebuffer height %u\n", r->height); |
150 | return -EINVAL; | 173 | return -EINVAL; |
151 | } | 174 | } |
152 | 175 | ||
153 | for (i = 0; i < info->num_planes; i++) { | 176 | for (i = 0; i < info->num_planes; i++) { |
154 | unsigned int width = r->width / (i != 0 ? info->hsub : 1); | 177 | unsigned int width = fb_plane_width(r->width, info, i); |
155 | unsigned int height = r->height / (i != 0 ? info->vsub : 1); | 178 | unsigned int height = fb_plane_height(r->height, info, i); |
156 | unsigned int cpp = info->cpp[i]; | 179 | unsigned int cpp = info->cpp[i]; |
157 | 180 | ||
158 | if (!r->handles[i]) { | 181 | if (!r->handles[i]) { |
@@ -263,7 +286,7 @@ drm_internal_framebuffer_create(struct drm_device *dev, | |||
263 | return ERR_PTR(-EINVAL); | 286 | return ERR_PTR(-EINVAL); |
264 | } | 287 | } |
265 | 288 | ||
266 | ret = framebuffer_check(r); | 289 | ret = framebuffer_check(dev, r); |
267 | if (ret) | 290 | if (ret) |
268 | return ERR_PTR(ret); | 291 | return ERR_PTR(ret); |
269 | 292 | ||
@@ -816,10 +839,7 @@ int drm_framebuffer_plane_width(int width, | |||
816 | if (plane >= fb->format->num_planes) | 839 | if (plane >= fb->format->num_planes) |
817 | return 0; | 840 | return 0; |
818 | 841 | ||
819 | if (plane == 0) | 842 | return fb_plane_width(width, fb->format, plane); |
820 | return width; | ||
821 | |||
822 | return width / fb->format->hsub; | ||
823 | } | 843 | } |
824 | EXPORT_SYMBOL(drm_framebuffer_plane_width); | 844 | EXPORT_SYMBOL(drm_framebuffer_plane_width); |
825 | 845 | ||
@@ -838,9 +858,6 @@ int drm_framebuffer_plane_height(int height, | |||
838 | if (plane >= fb->format->num_planes) | 858 | if (plane >= fb->format->num_planes) |
839 | return 0; | 859 | return 0; |
840 | 860 | ||
841 | if (plane == 0) | 861 | return fb_plane_height(height, fb->format, plane); |
842 | return height; | ||
843 | |||
844 | return height / fb->format->vsub; | ||
845 | } | 862 | } |
846 | EXPORT_SYMBOL(drm_framebuffer_plane_height); | 863 | EXPORT_SYMBOL(drm_framebuffer_plane_height); |
diff --git a/drivers/gpu/drm/drm_internal.h b/drivers/gpu/drm/drm_internal.h index 92ff4b9393b1..3d8e8f878924 100644 --- a/drivers/gpu/drm/drm_internal.h +++ b/drivers/gpu/drm/drm_internal.h | |||
@@ -100,7 +100,7 @@ int drm_gem_open_ioctl(struct drm_device *dev, void *data, | |||
100 | void drm_gem_open(struct drm_device *dev, struct drm_file *file_private); | 100 | void drm_gem_open(struct drm_device *dev, struct drm_file *file_private); |
101 | void drm_gem_release(struct drm_device *dev, struct drm_file *file_private); | 101 | void drm_gem_release(struct drm_device *dev, struct drm_file *file_private); |
102 | 102 | ||
103 | /* drm_debugfs.c */ | 103 | /* drm_debugfs.c drm_debugfs_crc.c */ |
104 | #if defined(CONFIG_DEBUG_FS) | 104 | #if defined(CONFIG_DEBUG_FS) |
105 | int drm_debugfs_init(struct drm_minor *minor, int minor_id, | 105 | int drm_debugfs_init(struct drm_minor *minor, int minor_id, |
106 | struct dentry *root); | 106 | struct dentry *root); |
diff --git a/drivers/gpu/drm/drm_ioctl.c b/drivers/gpu/drm/drm_ioctl.c index a7c61c23685a..7d6deaa91281 100644 --- a/drivers/gpu/drm/drm_ioctl.c +++ b/drivers/gpu/drm/drm_ioctl.c | |||
@@ -28,6 +28,7 @@ | |||
28 | * OTHER DEALINGS IN THE SOFTWARE. | 28 | * OTHER DEALINGS IN THE SOFTWARE. |
29 | */ | 29 | */ |
30 | 30 | ||
31 | #include <drm/drm_ioctl.h> | ||
31 | #include <drm/drmP.h> | 32 | #include <drm/drmP.h> |
32 | #include <drm/drm_auth.h> | 33 | #include <drm/drm_auth.h> |
33 | #include "drm_legacy.h" | 34 | #include "drm_legacy.h" |
diff --git a/drivers/gpu/drm/drm_irq.c b/drivers/gpu/drm/drm_irq.c index 53a526c7b24d..dac1b2593cb1 100644 --- a/drivers/gpu/drm/drm_irq.c +++ b/drivers/gpu/drm/drm_irq.c | |||
@@ -325,6 +325,8 @@ static void vblank_disable_and_save(struct drm_device *dev, unsigned int pipe) | |||
325 | struct drm_vblank_crtc *vblank = &dev->vblank[pipe]; | 325 | struct drm_vblank_crtc *vblank = &dev->vblank[pipe]; |
326 | unsigned long irqflags; | 326 | unsigned long irqflags; |
327 | 327 | ||
328 | assert_spin_locked(&dev->vbl_lock); | ||
329 | |||
328 | /* Prevent vblank irq processing while disabling vblank irqs, | 330 | /* Prevent vblank irq processing while disabling vblank irqs, |
329 | * so no updates of timestamps or count can happen after we've | 331 | * so no updates of timestamps or count can happen after we've |
330 | * disabled. Needed to prevent races in case of delayed irq's. | 332 | * disabled. Needed to prevent races in case of delayed irq's. |
@@ -384,7 +386,7 @@ void drm_vblank_cleanup(struct drm_device *dev) | |||
384 | for (pipe = 0; pipe < dev->num_crtcs; pipe++) { | 386 | for (pipe = 0; pipe < dev->num_crtcs; pipe++) { |
385 | struct drm_vblank_crtc *vblank = &dev->vblank[pipe]; | 387 | struct drm_vblank_crtc *vblank = &dev->vblank[pipe]; |
386 | 388 | ||
387 | WARN_ON(vblank->enabled && | 389 | WARN_ON(READ_ONCE(vblank->enabled) && |
388 | drm_core_check_feature(dev, DRIVER_MODESET)); | 390 | drm_core_check_feature(dev, DRIVER_MODESET)); |
389 | 391 | ||
390 | del_timer_sync(&vblank->disable_timer); | 392 | del_timer_sync(&vblank->disable_timer); |
@@ -810,14 +812,6 @@ int drm_calc_vbltimestamp_from_scanoutpos(struct drm_device *dev, | |||
810 | /* Return upper bound of timestamp precision error. */ | 812 | /* Return upper bound of timestamp precision error. */ |
811 | *max_error = duration_ns; | 813 | *max_error = duration_ns; |
812 | 814 | ||
813 | /* Check if in vblank area: | ||
814 | * vpos is >=0 in video scanout area, but negative | ||
815 | * within vblank area, counting down the number of lines until | ||
816 | * start of scanout. | ||
817 | */ | ||
818 | if (vbl_status & DRM_SCANOUTPOS_IN_VBLANK) | ||
819 | ret |= DRM_VBLANKTIME_IN_VBLANK; | ||
820 | |||
821 | /* Convert scanout position into elapsed time at raw_time query | 815 | /* Convert scanout position into elapsed time at raw_time query |
822 | * since start of scanout at first display scanline. delta_ns | 816 | * since start of scanout at first display scanline. delta_ns |
823 | * can be negative if start of scanout hasn't happened yet. | 817 | * can be negative if start of scanout hasn't happened yet. |
@@ -1105,11 +1099,16 @@ static int drm_vblank_enable(struct drm_device *dev, unsigned int pipe) | |||
1105 | */ | 1099 | */ |
1106 | ret = __enable_vblank(dev, pipe); | 1100 | ret = __enable_vblank(dev, pipe); |
1107 | DRM_DEBUG("enabling vblank on crtc %u, ret: %d\n", pipe, ret); | 1101 | DRM_DEBUG("enabling vblank on crtc %u, ret: %d\n", pipe, ret); |
1108 | if (ret) | 1102 | if (ret) { |
1109 | atomic_dec(&vblank->refcount); | 1103 | atomic_dec(&vblank->refcount); |
1110 | else { | 1104 | } else { |
1111 | vblank->enabled = true; | ||
1112 | drm_update_vblank_count(dev, pipe, 0); | 1105 | drm_update_vblank_count(dev, pipe, 0); |
1106 | /* drm_update_vblank_count() includes a wmb so we just | ||
1107 | * need to ensure that the compiler emits the write | ||
1108 | * to mark the vblank as enabled after the call | ||
1109 | * to drm_update_vblank_count(). | ||
1110 | */ | ||
1111 | WRITE_ONCE(vblank->enabled, true); | ||
1113 | } | 1112 | } |
1114 | } | 1113 | } |
1115 | 1114 | ||
@@ -1487,6 +1486,11 @@ int drm_legacy_modeset_ctl(struct drm_device *dev, void *data, | |||
1487 | return 0; | 1486 | return 0; |
1488 | } | 1487 | } |
1489 | 1488 | ||
1489 | static inline bool vblank_passed(u32 seq, u32 ref) | ||
1490 | { | ||
1491 | return (seq - ref) <= (1 << 23); | ||
1492 | } | ||
1493 | |||
1490 | static int drm_queue_vblank_event(struct drm_device *dev, unsigned int pipe, | 1494 | static int drm_queue_vblank_event(struct drm_device *dev, unsigned int pipe, |
1491 | union drm_wait_vblank *vblwait, | 1495 | union drm_wait_vblank *vblwait, |
1492 | struct drm_file *file_priv) | 1496 | struct drm_file *file_priv) |
@@ -1517,7 +1521,7 @@ static int drm_queue_vblank_event(struct drm_device *dev, unsigned int pipe, | |||
1517 | * vblank disable, so no need for further locking. The reference from | 1521 | * vblank disable, so no need for further locking. The reference from |
1518 | * drm_vblank_get() protects against vblank disable from another source. | 1522 | * drm_vblank_get() protects against vblank disable from another source. |
1519 | */ | 1523 | */ |
1520 | if (!vblank->enabled) { | 1524 | if (!READ_ONCE(vblank->enabled)) { |
1521 | ret = -EINVAL; | 1525 | ret = -EINVAL; |
1522 | goto err_unlock; | 1526 | goto err_unlock; |
1523 | } | 1527 | } |
@@ -1537,7 +1541,7 @@ static int drm_queue_vblank_event(struct drm_device *dev, unsigned int pipe, | |||
1537 | vblwait->request.sequence); | 1541 | vblwait->request.sequence); |
1538 | 1542 | ||
1539 | e->event.sequence = vblwait->request.sequence; | 1543 | e->event.sequence = vblwait->request.sequence; |
1540 | if ((seq - vblwait->request.sequence) <= (1 << 23)) { | 1544 | if (vblank_passed(seq, vblwait->request.sequence)) { |
1541 | drm_vblank_put(dev, pipe); | 1545 | drm_vblank_put(dev, pipe); |
1542 | send_vblank_event(dev, e, seq, &now); | 1546 | send_vblank_event(dev, e, seq, &now); |
1543 | vblwait->reply.sequence = seq; | 1547 | vblwait->reply.sequence = seq; |
@@ -1559,6 +1563,17 @@ err_put: | |||
1559 | return ret; | 1563 | return ret; |
1560 | } | 1564 | } |
1561 | 1565 | ||
1566 | static bool drm_wait_vblank_is_query(union drm_wait_vblank *vblwait) | ||
1567 | { | ||
1568 | if (vblwait->request.sequence) | ||
1569 | return false; | ||
1570 | |||
1571 | return _DRM_VBLANK_RELATIVE == | ||
1572 | (vblwait->request.type & (_DRM_VBLANK_TYPES_MASK | | ||
1573 | _DRM_VBLANK_EVENT | | ||
1574 | _DRM_VBLANK_NEXTONMISS)); | ||
1575 | } | ||
1576 | |||
1562 | /* | 1577 | /* |
1563 | * Wait for VBLANK. | 1578 | * Wait for VBLANK. |
1564 | * | 1579 | * |
@@ -1608,6 +1623,21 @@ int drm_wait_vblank(struct drm_device *dev, void *data, | |||
1608 | 1623 | ||
1609 | vblank = &dev->vblank[pipe]; | 1624 | vblank = &dev->vblank[pipe]; |
1610 | 1625 | ||
1626 | /* If the counter is currently enabled and accurate, short-circuit | ||
1627 | * queries to return the cached timestamp of the last vblank. | ||
1628 | */ | ||
1629 | if (dev->vblank_disable_immediate && | ||
1630 | drm_wait_vblank_is_query(vblwait) && | ||
1631 | READ_ONCE(vblank->enabled)) { | ||
1632 | struct timeval now; | ||
1633 | |||
1634 | vblwait->reply.sequence = | ||
1635 | drm_vblank_count_and_time(dev, pipe, &now); | ||
1636 | vblwait->reply.tval_sec = now.tv_sec; | ||
1637 | vblwait->reply.tval_usec = now.tv_usec; | ||
1638 | return 0; | ||
1639 | } | ||
1640 | |||
1611 | ret = drm_vblank_get(dev, pipe); | 1641 | ret = drm_vblank_get(dev, pipe); |
1612 | if (ret) { | 1642 | if (ret) { |
1613 | DRM_DEBUG("crtc %d failed to acquire vblank counter, %d\n", pipe, ret); | 1643 | DRM_DEBUG("crtc %d failed to acquire vblank counter, %d\n", pipe, ret); |
@@ -1627,9 +1657,8 @@ int drm_wait_vblank(struct drm_device *dev, void *data, | |||
1627 | } | 1657 | } |
1628 | 1658 | ||
1629 | if ((flags & _DRM_VBLANK_NEXTONMISS) && | 1659 | if ((flags & _DRM_VBLANK_NEXTONMISS) && |
1630 | (seq - vblwait->request.sequence) <= (1 << 23)) { | 1660 | vblank_passed(seq, vblwait->request.sequence)) |
1631 | vblwait->request.sequence = seq + 1; | 1661 | vblwait->request.sequence = seq + 1; |
1632 | } | ||
1633 | 1662 | ||
1634 | if (flags & _DRM_VBLANK_EVENT) { | 1663 | if (flags & _DRM_VBLANK_EVENT) { |
1635 | /* must hold on to the vblank ref until the event fires | 1664 | /* must hold on to the vblank ref until the event fires |
@@ -1642,10 +1671,9 @@ int drm_wait_vblank(struct drm_device *dev, void *data, | |||
1642 | DRM_DEBUG("waiting on vblank count %u, crtc %u\n", | 1671 | DRM_DEBUG("waiting on vblank count %u, crtc %u\n", |
1643 | vblwait->request.sequence, pipe); | 1672 | vblwait->request.sequence, pipe); |
1644 | DRM_WAIT_ON(ret, vblank->queue, 3 * HZ, | 1673 | DRM_WAIT_ON(ret, vblank->queue, 3 * HZ, |
1645 | (((drm_vblank_count(dev, pipe) - | 1674 | vblank_passed(drm_vblank_count(dev, pipe), |
1646 | vblwait->request.sequence) <= (1 << 23)) || | 1675 | vblwait->request.sequence) || |
1647 | !vblank->enabled || | 1676 | !READ_ONCE(vblank->enabled)); |
1648 | !dev->irq_enabled)); | ||
1649 | } | 1677 | } |
1650 | 1678 | ||
1651 | if (ret != -EINTR) { | 1679 | if (ret != -EINTR) { |
@@ -1679,7 +1707,7 @@ static void drm_handle_vblank_events(struct drm_device *dev, unsigned int pipe) | |||
1679 | list_for_each_entry_safe(e, t, &dev->vblank_event_list, base.link) { | 1707 | list_for_each_entry_safe(e, t, &dev->vblank_event_list, base.link) { |
1680 | if (e->pipe != pipe) | 1708 | if (e->pipe != pipe) |
1681 | continue; | 1709 | continue; |
1682 | if ((seq - e->event.sequence) > (1<<23)) | 1710 | if (!vblank_passed(seq, e->event.sequence)) |
1683 | continue; | 1711 | continue; |
1684 | 1712 | ||
1685 | DRM_DEBUG("vblank event on %u, current %u\n", | 1713 | DRM_DEBUG("vblank event on %u, current %u\n", |
@@ -1707,6 +1735,7 @@ bool drm_handle_vblank(struct drm_device *dev, unsigned int pipe) | |||
1707 | { | 1735 | { |
1708 | struct drm_vblank_crtc *vblank = &dev->vblank[pipe]; | 1736 | struct drm_vblank_crtc *vblank = &dev->vblank[pipe]; |
1709 | unsigned long irqflags; | 1737 | unsigned long irqflags; |
1738 | bool disable_irq; | ||
1710 | 1739 | ||
1711 | if (WARN_ON_ONCE(!dev->num_crtcs)) | 1740 | if (WARN_ON_ONCE(!dev->num_crtcs)) |
1712 | return false; | 1741 | return false; |
@@ -1734,20 +1763,23 @@ bool drm_handle_vblank(struct drm_device *dev, unsigned int pipe) | |||
1734 | spin_unlock(&dev->vblank_time_lock); | 1763 | spin_unlock(&dev->vblank_time_lock); |
1735 | 1764 | ||
1736 | wake_up(&vblank->queue); | 1765 | wake_up(&vblank->queue); |
1737 | drm_handle_vblank_events(dev, pipe); | ||
1738 | 1766 | ||
1739 | /* With instant-off, we defer disabling the interrupt until after | 1767 | /* With instant-off, we defer disabling the interrupt until after |
1740 | * we finish processing the following vblank. The disable has to | 1768 | * we finish processing the following vblank after all events have |
1741 | * be last (after drm_handle_vblank_events) so that the timestamp | 1769 | * been signaled. The disable has to be last (after |
1742 | * is always accurate. | 1770 | * drm_handle_vblank_events) so that the timestamp is always accurate. |
1743 | */ | 1771 | */ |
1744 | if (dev->vblank_disable_immediate && | 1772 | disable_irq = (dev->vblank_disable_immediate && |
1745 | drm_vblank_offdelay > 0 && | 1773 | drm_vblank_offdelay > 0 && |
1746 | !atomic_read(&vblank->refcount)) | 1774 | !atomic_read(&vblank->refcount)); |
1747 | vblank_disable_fn((unsigned long)vblank); | 1775 | |
1776 | drm_handle_vblank_events(dev, pipe); | ||
1748 | 1777 | ||
1749 | spin_unlock_irqrestore(&dev->event_lock, irqflags); | 1778 | spin_unlock_irqrestore(&dev->event_lock, irqflags); |
1750 | 1779 | ||
1780 | if (disable_irq) | ||
1781 | vblank_disable_fn((unsigned long)vblank); | ||
1782 | |||
1751 | return true; | 1783 | return true; |
1752 | } | 1784 | } |
1753 | EXPORT_SYMBOL(drm_handle_vblank); | 1785 | EXPORT_SYMBOL(drm_handle_vblank); |
diff --git a/drivers/gpu/drm/drm_modeset_helper.c b/drivers/gpu/drm/drm_modeset_helper.c index cc44a9a4b004..2b33825f2f93 100644 --- a/drivers/gpu/drm/drm_modeset_helper.c +++ b/drivers/gpu/drm/drm_modeset_helper.c | |||
@@ -78,7 +78,7 @@ void drm_helper_mode_fill_fb_struct(struct drm_device *dev, | |||
78 | int i; | 78 | int i; |
79 | 79 | ||
80 | fb->dev = dev; | 80 | fb->dev = dev; |
81 | fb->format = drm_format_info(mode_cmd->pixel_format); | 81 | fb->format = drm_get_format_info(dev, mode_cmd); |
82 | fb->width = mode_cmd->width; | 82 | fb->width = mode_cmd->width; |
83 | fb->height = mode_cmd->height; | 83 | fb->height = mode_cmd->height; |
84 | for (i = 0; i < 4; i++) { | 84 | for (i = 0; i < 4; i++) { |
diff --git a/drivers/gpu/drm/drm_plane.c b/drivers/gpu/drm/drm_plane.c index a22e76837065..bc71aa2b7872 100644 --- a/drivers/gpu/drm/drm_plane.c +++ b/drivers/gpu/drm/drm_plane.c | |||
@@ -277,6 +277,12 @@ EXPORT_SYMBOL(drm_plane_from_index); | |||
277 | * | 277 | * |
278 | * Used when the plane's current framebuffer is destroyed, | 278 | * Used when the plane's current framebuffer is destroyed, |
279 | * and when restoring fbdev mode. | 279 | * and when restoring fbdev mode. |
280 | * | ||
281 | * Note that this function is not suitable for atomic drivers, since it doesn't | ||
282 | * wire through the lock acquisition context properly and hence can't handle | ||
283 | * retries or driver private locks. You probably want to use | ||
284 | * drm_atomic_helper_disable_plane() or | ||
285 | * drm_atomic_helper_disable_planes_on_crtc() instead. | ||
280 | */ | 286 | */ |
281 | void drm_plane_force_disable(struct drm_plane *plane) | 287 | void drm_plane_force_disable(struct drm_plane *plane) |
282 | { | 288 | { |
@@ -285,8 +291,10 @@ void drm_plane_force_disable(struct drm_plane *plane) | |||
285 | if (!plane->fb) | 291 | if (!plane->fb) |
286 | return; | 292 | return; |
287 | 293 | ||
294 | WARN_ON(drm_drv_uses_atomic_modeset(plane->dev)); | ||
295 | |||
288 | plane->old_fb = plane->fb; | 296 | plane->old_fb = plane->fb; |
289 | ret = plane->funcs->disable_plane(plane); | 297 | ret = plane->funcs->disable_plane(plane, NULL); |
290 | if (ret) { | 298 | if (ret) { |
291 | DRM_ERROR("failed to disable plane with busy fb\n"); | 299 | DRM_ERROR("failed to disable plane with busy fb\n"); |
292 | plane->old_fb = NULL; | 300 | plane->old_fb = NULL; |
@@ -457,14 +465,15 @@ static int __setplane_internal(struct drm_plane *plane, | |||
457 | uint32_t crtc_w, uint32_t crtc_h, | 465 | uint32_t crtc_w, uint32_t crtc_h, |
458 | /* src_{x,y,w,h} values are 16.16 fixed point */ | 466 | /* src_{x,y,w,h} values are 16.16 fixed point */ |
459 | uint32_t src_x, uint32_t src_y, | 467 | uint32_t src_x, uint32_t src_y, |
460 | uint32_t src_w, uint32_t src_h) | 468 | uint32_t src_w, uint32_t src_h, |
469 | struct drm_modeset_acquire_ctx *ctx) | ||
461 | { | 470 | { |
462 | int ret = 0; | 471 | int ret = 0; |
463 | 472 | ||
464 | /* No fb means shut it down */ | 473 | /* No fb means shut it down */ |
465 | if (!fb) { | 474 | if (!fb) { |
466 | plane->old_fb = plane->fb; | 475 | plane->old_fb = plane->fb; |
467 | ret = plane->funcs->disable_plane(plane); | 476 | ret = plane->funcs->disable_plane(plane, ctx); |
468 | if (!ret) { | 477 | if (!ret) { |
469 | plane->crtc = NULL; | 478 | plane->crtc = NULL; |
470 | plane->fb = NULL; | 479 | plane->fb = NULL; |
@@ -509,7 +518,7 @@ static int __setplane_internal(struct drm_plane *plane, | |||
509 | plane->old_fb = plane->fb; | 518 | plane->old_fb = plane->fb; |
510 | ret = plane->funcs->update_plane(plane, crtc, fb, | 519 | ret = plane->funcs->update_plane(plane, crtc, fb, |
511 | crtc_x, crtc_y, crtc_w, crtc_h, | 520 | crtc_x, crtc_y, crtc_w, crtc_h, |
512 | src_x, src_y, src_w, src_h); | 521 | src_x, src_y, src_w, src_h, ctx); |
513 | if (!ret) { | 522 | if (!ret) { |
514 | plane->crtc = crtc; | 523 | plane->crtc = crtc; |
515 | plane->fb = fb; | 524 | plane->fb = fb; |
@@ -537,13 +546,25 @@ static int setplane_internal(struct drm_plane *plane, | |||
537 | uint32_t src_x, uint32_t src_y, | 546 | uint32_t src_x, uint32_t src_y, |
538 | uint32_t src_w, uint32_t src_h) | 547 | uint32_t src_w, uint32_t src_h) |
539 | { | 548 | { |
549 | struct drm_modeset_acquire_ctx ctx; | ||
540 | int ret; | 550 | int ret; |
541 | 551 | ||
542 | drm_modeset_lock_all(plane->dev); | 552 | drm_modeset_acquire_init(&ctx, 0); |
553 | retry: | ||
554 | ret = drm_modeset_lock_all_ctx(plane->dev, &ctx); | ||
555 | if (ret) | ||
556 | goto fail; | ||
543 | ret = __setplane_internal(plane, crtc, fb, | 557 | ret = __setplane_internal(plane, crtc, fb, |
544 | crtc_x, crtc_y, crtc_w, crtc_h, | 558 | crtc_x, crtc_y, crtc_w, crtc_h, |
545 | src_x, src_y, src_w, src_h); | 559 | src_x, src_y, src_w, src_h, &ctx); |
546 | drm_modeset_unlock_all(plane->dev); | 560 | |
561 | fail: | ||
562 | if (ret == -EDEADLK) { | ||
563 | drm_modeset_backoff(&ctx); | ||
564 | goto retry; | ||
565 | } | ||
566 | drm_modeset_drop_locks(&ctx); | ||
567 | drm_modeset_acquire_fini(&ctx); | ||
547 | 568 | ||
548 | return ret; | 569 | return ret; |
549 | } | 570 | } |
@@ -613,11 +634,21 @@ static int drm_mode_cursor_universal(struct drm_crtc *crtc, | |||
613 | int32_t crtc_x, crtc_y; | 634 | int32_t crtc_x, crtc_y; |
614 | uint32_t crtc_w = 0, crtc_h = 0; | 635 | uint32_t crtc_w = 0, crtc_h = 0; |
615 | uint32_t src_w = 0, src_h = 0; | 636 | uint32_t src_w = 0, src_h = 0; |
637 | struct drm_modeset_acquire_ctx ctx; | ||
616 | int ret = 0; | 638 | int ret = 0; |
617 | 639 | ||
618 | BUG_ON(!crtc->cursor); | 640 | BUG_ON(!crtc->cursor); |
619 | WARN_ON(crtc->cursor->crtc != crtc && crtc->cursor->crtc != NULL); | 641 | WARN_ON(crtc->cursor->crtc != crtc && crtc->cursor->crtc != NULL); |
620 | 642 | ||
643 | drm_modeset_acquire_init(&ctx, 0); | ||
644 | retry: | ||
645 | ret = drm_modeset_lock(&crtc->mutex, &ctx); | ||
646 | if (ret) | ||
647 | goto fail; | ||
648 | ret = drm_modeset_lock(&crtc->cursor->mutex, &ctx); | ||
649 | if (ret) | ||
650 | goto fail; | ||
651 | |||
621 | /* | 652 | /* |
622 | * Obtain fb we'll be using (either new or existing) and take an extra | 653 | * Obtain fb we'll be using (either new or existing) and take an extra |
623 | * reference to it if fb != null. setplane will take care of dropping | 654 | * reference to it if fb != null. setplane will take care of dropping |
@@ -662,7 +693,7 @@ static int drm_mode_cursor_universal(struct drm_crtc *crtc, | |||
662 | */ | 693 | */ |
663 | ret = __setplane_internal(crtc->cursor, crtc, fb, | 694 | ret = __setplane_internal(crtc->cursor, crtc, fb, |
664 | crtc_x, crtc_y, crtc_w, crtc_h, | 695 | crtc_x, crtc_y, crtc_w, crtc_h, |
665 | 0, 0, src_w, src_h); | 696 | 0, 0, src_w, src_h, &ctx); |
666 | 697 | ||
667 | /* Update successful; save new cursor position, if necessary */ | 698 | /* Update successful; save new cursor position, if necessary */ |
668 | if (ret == 0 && req->flags & DRM_MODE_CURSOR_MOVE) { | 699 | if (ret == 0 && req->flags & DRM_MODE_CURSOR_MOVE) { |
@@ -670,6 +701,15 @@ static int drm_mode_cursor_universal(struct drm_crtc *crtc, | |||
670 | crtc->cursor_y = req->y; | 701 | crtc->cursor_y = req->y; |
671 | } | 702 | } |
672 | 703 | ||
704 | fail: | ||
705 | if (ret == -EDEADLK) { | ||
706 | drm_modeset_backoff(&ctx); | ||
707 | goto retry; | ||
708 | } | ||
709 | |||
710 | drm_modeset_drop_locks(&ctx); | ||
711 | drm_modeset_acquire_fini(&ctx); | ||
712 | |||
673 | return ret; | 713 | return ret; |
674 | } | 714 | } |
675 | 715 | ||
@@ -696,12 +736,10 @@ static int drm_mode_cursor_common(struct drm_device *dev, | |||
696 | * If this crtc has a universal cursor plane, call that plane's update | 736 | * If this crtc has a universal cursor plane, call that plane's update |
697 | * handler rather than using legacy cursor handlers. | 737 | * handler rather than using legacy cursor handlers. |
698 | */ | 738 | */ |
699 | drm_modeset_lock_crtc(crtc, crtc->cursor); | 739 | if (crtc->cursor) |
700 | if (crtc->cursor) { | 740 | return drm_mode_cursor_universal(crtc, req, file_priv); |
701 | ret = drm_mode_cursor_universal(crtc, req, file_priv); | ||
702 | goto out; | ||
703 | } | ||
704 | 741 | ||
742 | drm_modeset_lock_crtc(crtc, crtc->cursor); | ||
705 | if (req->flags & DRM_MODE_CURSOR_BO) { | 743 | if (req->flags & DRM_MODE_CURSOR_BO) { |
706 | if (!crtc->funcs->cursor_set && !crtc->funcs->cursor_set2) { | 744 | if (!crtc->funcs->cursor_set && !crtc->funcs->cursor_set2) { |
707 | ret = -ENXIO; | 745 | ret = -ENXIO; |
@@ -765,6 +803,7 @@ int drm_mode_page_flip_ioctl(struct drm_device *dev, | |||
765 | struct drm_framebuffer *fb = NULL; | 803 | struct drm_framebuffer *fb = NULL; |
766 | struct drm_pending_vblank_event *e = NULL; | 804 | struct drm_pending_vblank_event *e = NULL; |
767 | u32 target_vblank = page_flip->sequence; | 805 | u32 target_vblank = page_flip->sequence; |
806 | struct drm_modeset_acquire_ctx ctx; | ||
768 | int ret = -EINVAL; | 807 | int ret = -EINVAL; |
769 | 808 | ||
770 | if (!drm_core_check_feature(dev, DRIVER_MODESET)) | 809 | if (!drm_core_check_feature(dev, DRIVER_MODESET)) |
@@ -828,7 +867,15 @@ int drm_mode_page_flip_ioctl(struct drm_device *dev, | |||
828 | return -EINVAL; | 867 | return -EINVAL; |
829 | } | 868 | } |
830 | 869 | ||
831 | drm_modeset_lock_crtc(crtc, crtc->primary); | 870 | drm_modeset_acquire_init(&ctx, 0); |
871 | retry: | ||
872 | ret = drm_modeset_lock(&crtc->mutex, &ctx); | ||
873 | if (ret) | ||
874 | goto out; | ||
875 | ret = drm_modeset_lock(&crtc->primary->mutex, &ctx); | ||
876 | if (ret) | ||
877 | goto out; | ||
878 | |||
832 | if (crtc->primary->fb == NULL) { | 879 | if (crtc->primary->fb == NULL) { |
833 | /* The framebuffer is currently unbound, presumably | 880 | /* The framebuffer is currently unbound, presumably |
834 | * due to a hotplug event, that userspace has not | 881 | * due to a hotplug event, that userspace has not |
@@ -876,6 +923,7 @@ int drm_mode_page_flip_ioctl(struct drm_device *dev, | |||
876 | ret = drm_event_reserve_init(dev, file_priv, &e->base, &e->event.base); | 923 | ret = drm_event_reserve_init(dev, file_priv, &e->base, &e->event.base); |
877 | if (ret) { | 924 | if (ret) { |
878 | kfree(e); | 925 | kfree(e); |
926 | e = NULL; | ||
879 | goto out; | 927 | goto out; |
880 | } | 928 | } |
881 | } | 929 | } |
@@ -884,9 +932,11 @@ int drm_mode_page_flip_ioctl(struct drm_device *dev, | |||
884 | if (crtc->funcs->page_flip_target) | 932 | if (crtc->funcs->page_flip_target) |
885 | ret = crtc->funcs->page_flip_target(crtc, fb, e, | 933 | ret = crtc->funcs->page_flip_target(crtc, fb, e, |
886 | page_flip->flags, | 934 | page_flip->flags, |
887 | target_vblank); | 935 | target_vblank, |
936 | &ctx); | ||
888 | else | 937 | else |
889 | ret = crtc->funcs->page_flip(crtc, fb, e, page_flip->flags); | 938 | ret = crtc->funcs->page_flip(crtc, fb, e, page_flip->flags, |
939 | &ctx); | ||
890 | if (ret) { | 940 | if (ret) { |
891 | if (page_flip->flags & DRM_MODE_PAGE_FLIP_EVENT) | 941 | if (page_flip->flags & DRM_MODE_PAGE_FLIP_EVENT) |
892 | drm_event_cancel_free(dev, &e->base); | 942 | drm_event_cancel_free(dev, &e->base); |
@@ -906,7 +956,14 @@ out: | |||
906 | if (crtc->primary->old_fb) | 956 | if (crtc->primary->old_fb) |
907 | drm_framebuffer_put(crtc->primary->old_fb); | 957 | drm_framebuffer_put(crtc->primary->old_fb); |
908 | crtc->primary->old_fb = NULL; | 958 | crtc->primary->old_fb = NULL; |
909 | drm_modeset_unlock_crtc(crtc); | 959 | |
960 | if (ret == -EDEADLK) { | ||
961 | drm_modeset_backoff(&ctx); | ||
962 | goto retry; | ||
963 | } | ||
964 | |||
965 | drm_modeset_drop_locks(&ctx); | ||
966 | drm_modeset_acquire_fini(&ctx); | ||
910 | 967 | ||
911 | return ret; | 968 | return ret; |
912 | } | 969 | } |
diff --git a/drivers/gpu/drm/drm_plane_helper.c b/drivers/gpu/drm/drm_plane_helper.c index de1ac5e08f4d..b84a295230fc 100644 --- a/drivers/gpu/drm/drm_plane_helper.c +++ b/drivers/gpu/drm/drm_plane_helper.c | |||
@@ -275,6 +275,7 @@ EXPORT_SYMBOL(drm_plane_helper_check_update); | |||
275 | * @src_y: y offset of @fb for panning | 275 | * @src_y: y offset of @fb for panning |
276 | * @src_w: width of source rectangle in @fb | 276 | * @src_w: width of source rectangle in @fb |
277 | * @src_h: height of source rectangle in @fb | 277 | * @src_h: height of source rectangle in @fb |
278 | * @ctx: lock acquire context, not used here | ||
278 | * | 279 | * |
279 | * Provides a default plane update handler for primary planes. This is handler | 280 | * Provides a default plane update handler for primary planes. This is handler |
280 | * is called in response to a userspace SetPlane operation on the plane with a | 281 | * is called in response to a userspace SetPlane operation on the plane with a |
@@ -303,7 +304,8 @@ int drm_primary_helper_update(struct drm_plane *plane, struct drm_crtc *crtc, | |||
303 | int crtc_x, int crtc_y, | 304 | int crtc_x, int crtc_y, |
304 | unsigned int crtc_w, unsigned int crtc_h, | 305 | unsigned int crtc_w, unsigned int crtc_h, |
305 | uint32_t src_x, uint32_t src_y, | 306 | uint32_t src_x, uint32_t src_y, |
306 | uint32_t src_w, uint32_t src_h) | 307 | uint32_t src_w, uint32_t src_h, |
308 | struct drm_modeset_acquire_ctx *ctx) | ||
307 | { | 309 | { |
308 | struct drm_mode_set set = { | 310 | struct drm_mode_set set = { |
309 | .crtc = crtc, | 311 | .crtc = crtc, |
@@ -347,7 +349,7 @@ int drm_primary_helper_update(struct drm_plane *plane, struct drm_crtc *crtc, | |||
347 | * provides their own disable function, this will just | 349 | * provides their own disable function, this will just |
348 | * wind up returning -EINVAL to userspace. | 350 | * wind up returning -EINVAL to userspace. |
349 | */ | 351 | */ |
350 | return plane->funcs->disable_plane(plane); | 352 | return plane->funcs->disable_plane(plane, ctx); |
351 | 353 | ||
352 | /* Find current connectors for CRTC */ | 354 | /* Find current connectors for CRTC */ |
353 | num_connectors = get_connectors_for_crtc(crtc, NULL, 0); | 355 | num_connectors = get_connectors_for_crtc(crtc, NULL, 0); |
@@ -369,7 +371,7 @@ int drm_primary_helper_update(struct drm_plane *plane, struct drm_crtc *crtc, | |||
369 | * drm_mode_setplane() already handles the basic refcounting for the | 371 | * drm_mode_setplane() already handles the basic refcounting for the |
370 | * framebuffers involved in this operation. | 372 | * framebuffers involved in this operation. |
371 | */ | 373 | */ |
372 | ret = crtc->funcs->set_config(&set); | 374 | ret = crtc->funcs->set_config(&set, ctx); |
373 | 375 | ||
374 | kfree(connector_list); | 376 | kfree(connector_list); |
375 | return ret; | 377 | return ret; |
@@ -396,7 +398,8 @@ EXPORT_SYMBOL(drm_primary_helper_update); | |||
396 | * RETURNS: | 398 | * RETURNS: |
397 | * Unconditionally returns -EINVAL. | 399 | * Unconditionally returns -EINVAL. |
398 | */ | 400 | */ |
399 | int drm_primary_helper_disable(struct drm_plane *plane) | 401 | int drm_primary_helper_disable(struct drm_plane *plane, |
402 | struct drm_modeset_acquire_ctx *ctx) | ||
400 | { | 403 | { |
401 | return -EINVAL; | 404 | return -EINVAL; |
402 | } | 405 | } |
diff --git a/drivers/gpu/drm/drm_simple_kms_helper.c b/drivers/gpu/drm/drm_simple_kms_helper.c index 16789faa9291..e084f9f8ca66 100644 --- a/drivers/gpu/drm/drm_simple_kms_helper.c +++ b/drivers/gpu/drm/drm_simple_kms_helper.c | |||
@@ -114,7 +114,7 @@ static int drm_simple_kms_plane_atomic_check(struct drm_plane *plane, | |||
114 | } | 114 | } |
115 | 115 | ||
116 | static void drm_simple_kms_plane_atomic_update(struct drm_plane *plane, | 116 | static void drm_simple_kms_plane_atomic_update(struct drm_plane *plane, |
117 | struct drm_plane_state *pstate) | 117 | struct drm_plane_state *old_pstate) |
118 | { | 118 | { |
119 | struct drm_simple_display_pipe *pipe; | 119 | struct drm_simple_display_pipe *pipe; |
120 | 120 | ||
@@ -122,7 +122,7 @@ static void drm_simple_kms_plane_atomic_update(struct drm_plane *plane, | |||
122 | if (!pipe->funcs || !pipe->funcs->update) | 122 | if (!pipe->funcs || !pipe->funcs->update) |
123 | return; | 123 | return; |
124 | 124 | ||
125 | pipe->funcs->update(pipe, pstate); | 125 | pipe->funcs->update(pipe, old_pstate); |
126 | } | 126 | } |
127 | 127 | ||
128 | static int drm_simple_kms_plane_prepare_fb(struct drm_plane *plane, | 128 | static int drm_simple_kms_plane_prepare_fb(struct drm_plane *plane, |
diff --git a/drivers/gpu/drm/gma500/gma_display.c b/drivers/gpu/drm/gma500/gma_display.c index d1c5642b1c1e..93ff46535c04 100644 --- a/drivers/gpu/drm/gma500/gma_display.c +++ b/drivers/gpu/drm/gma500/gma_display.c | |||
@@ -514,17 +514,18 @@ void gma_crtc_destroy(struct drm_crtc *crtc) | |||
514 | kfree(gma_crtc); | 514 | kfree(gma_crtc); |
515 | } | 515 | } |
516 | 516 | ||
517 | int gma_crtc_set_config(struct drm_mode_set *set) | 517 | int gma_crtc_set_config(struct drm_mode_set *set, |
518 | struct drm_modeset_acquire_ctx *ctx) | ||
518 | { | 519 | { |
519 | struct drm_device *dev = set->crtc->dev; | 520 | struct drm_device *dev = set->crtc->dev; |
520 | struct drm_psb_private *dev_priv = dev->dev_private; | 521 | struct drm_psb_private *dev_priv = dev->dev_private; |
521 | int ret; | 522 | int ret; |
522 | 523 | ||
523 | if (!dev_priv->rpm_enabled) | 524 | if (!dev_priv->rpm_enabled) |
524 | return drm_crtc_helper_set_config(set); | 525 | return drm_crtc_helper_set_config(set, ctx); |
525 | 526 | ||
526 | pm_runtime_forbid(&dev->pdev->dev); | 527 | pm_runtime_forbid(&dev->pdev->dev); |
527 | ret = drm_crtc_helper_set_config(set); | 528 | ret = drm_crtc_helper_set_config(set, ctx); |
528 | pm_runtime_allow(&dev->pdev->dev); | 529 | pm_runtime_allow(&dev->pdev->dev); |
529 | 530 | ||
530 | return ret; | 531 | return ret; |
diff --git a/drivers/gpu/drm/gma500/gma_display.h b/drivers/gpu/drm/gma500/gma_display.h index e72dd08b701b..166e608923db 100644 --- a/drivers/gpu/drm/gma500/gma_display.h +++ b/drivers/gpu/drm/gma500/gma_display.h | |||
@@ -79,7 +79,8 @@ extern void gma_crtc_prepare(struct drm_crtc *crtc); | |||
79 | extern void gma_crtc_commit(struct drm_crtc *crtc); | 79 | extern void gma_crtc_commit(struct drm_crtc *crtc); |
80 | extern void gma_crtc_disable(struct drm_crtc *crtc); | 80 | extern void gma_crtc_disable(struct drm_crtc *crtc); |
81 | extern void gma_crtc_destroy(struct drm_crtc *crtc); | 81 | extern void gma_crtc_destroy(struct drm_crtc *crtc); |
82 | extern int gma_crtc_set_config(struct drm_mode_set *set); | 82 | extern int gma_crtc_set_config(struct drm_mode_set *set, |
83 | struct drm_modeset_acquire_ctx *ctx); | ||
83 | 84 | ||
84 | extern void gma_crtc_save(struct drm_crtc *crtc); | 85 | extern void gma_crtc_save(struct drm_crtc *crtc); |
85 | extern void gma_crtc_restore(struct drm_crtc *crtc); | 86 | extern void gma_crtc_restore(struct drm_crtc *crtc); |
diff --git a/drivers/gpu/drm/i915/i915_drv.c b/drivers/gpu/drm/i915/i915_drv.c index 03d9e45694c9..98b17070a123 100644 --- a/drivers/gpu/drm/i915/i915_drv.c +++ b/drivers/gpu/drm/i915/i915_drv.c | |||
@@ -1307,8 +1307,6 @@ void i915_driver_unload(struct drm_device *dev) | |||
1307 | { | 1307 | { |
1308 | struct drm_i915_private *dev_priv = to_i915(dev); | 1308 | struct drm_i915_private *dev_priv = to_i915(dev); |
1309 | struct pci_dev *pdev = dev_priv->drm.pdev; | 1309 | struct pci_dev *pdev = dev_priv->drm.pdev; |
1310 | struct drm_modeset_acquire_ctx ctx; | ||
1311 | int ret; | ||
1312 | 1310 | ||
1313 | intel_fbdev_fini(dev); | 1311 | intel_fbdev_fini(dev); |
1314 | 1312 | ||
@@ -1317,23 +1315,7 @@ void i915_driver_unload(struct drm_device *dev) | |||
1317 | 1315 | ||
1318 | intel_display_power_get(dev_priv, POWER_DOMAIN_INIT); | 1316 | intel_display_power_get(dev_priv, POWER_DOMAIN_INIT); |
1319 | 1317 | ||
1320 | drm_modeset_acquire_init(&ctx, 0); | 1318 | drm_atomic_helper_shutdown(dev); |
1321 | while (1) { | ||
1322 | ret = drm_modeset_lock_all_ctx(dev, &ctx); | ||
1323 | if (!ret) | ||
1324 | ret = drm_atomic_helper_disable_all(dev, &ctx); | ||
1325 | |||
1326 | if (ret != -EDEADLK) | ||
1327 | break; | ||
1328 | |||
1329 | drm_modeset_backoff(&ctx); | ||
1330 | } | ||
1331 | |||
1332 | if (ret) | ||
1333 | DRM_ERROR("Disabling all crtc's during unload failed with %i\n", ret); | ||
1334 | |||
1335 | drm_modeset_drop_locks(&ctx); | ||
1336 | drm_modeset_acquire_fini(&ctx); | ||
1337 | 1319 | ||
1338 | intel_gvt_cleanup(dev_priv); | 1320 | intel_gvt_cleanup(dev_priv); |
1339 | 1321 | ||
diff --git a/drivers/gpu/drm/i915/intel_display.c b/drivers/gpu/drm/i915/intel_display.c index 010e5ddb198a..e27ea89efd67 100644 --- a/drivers/gpu/drm/i915/intel_display.c +++ b/drivers/gpu/drm/i915/intel_display.c | |||
@@ -13426,7 +13426,8 @@ intel_legacy_cursor_update(struct drm_plane *plane, | |||
13426 | int crtc_x, int crtc_y, | 13426 | int crtc_x, int crtc_y, |
13427 | unsigned int crtc_w, unsigned int crtc_h, | 13427 | unsigned int crtc_w, unsigned int crtc_h, |
13428 | uint32_t src_x, uint32_t src_y, | 13428 | uint32_t src_x, uint32_t src_y, |
13429 | uint32_t src_w, uint32_t src_h) | 13429 | uint32_t src_w, uint32_t src_h, |
13430 | struct drm_modeset_acquire_ctx *ctx) | ||
13430 | { | 13431 | { |
13431 | struct drm_i915_private *dev_priv = to_i915(crtc->dev); | 13432 | struct drm_i915_private *dev_priv = to_i915(crtc->dev); |
13432 | int ret; | 13433 | int ret; |
@@ -13539,7 +13540,7 @@ out_free: | |||
13539 | slow: | 13540 | slow: |
13540 | return drm_atomic_helper_update_plane(plane, crtc, fb, | 13541 | return drm_atomic_helper_update_plane(plane, crtc, fb, |
13541 | crtc_x, crtc_y, crtc_w, crtc_h, | 13542 | crtc_x, crtc_y, crtc_w, crtc_h, |
13542 | src_x, src_y, src_w, src_h); | 13543 | src_x, src_y, src_w, src_h, ctx); |
13543 | } | 13544 | } |
13544 | 13545 | ||
13545 | static const struct drm_plane_funcs intel_cursor_plane_funcs = { | 13546 | static const struct drm_plane_funcs intel_cursor_plane_funcs = { |
diff --git a/drivers/gpu/drm/i915/intel_dp_mst.c b/drivers/gpu/drm/i915/intel_dp_mst.c index 094cbdcbcd6d..c1f62eb07c07 100644 --- a/drivers/gpu/drm/i915/intel_dp_mst.c +++ b/drivers/gpu/drm/i915/intel_dp_mst.c | |||
@@ -149,7 +149,6 @@ static void intel_mst_pre_enable_dp(struct intel_encoder *encoder, | |||
149 | to_intel_connector(conn_state->connector); | 149 | to_intel_connector(conn_state->connector); |
150 | int ret; | 150 | int ret; |
151 | uint32_t temp; | 151 | uint32_t temp; |
152 | int slots; | ||
153 | 152 | ||
154 | /* MST encoders are bound to a crtc, not to a connector, | 153 | /* MST encoders are bound to a crtc, not to a connector, |
155 | * force the mapping here for get_hw_state. | 154 | * force the mapping here for get_hw_state. |
@@ -165,7 +164,8 @@ static void intel_mst_pre_enable_dp(struct intel_encoder *encoder, | |||
165 | 164 | ||
166 | ret = drm_dp_mst_allocate_vcpi(&intel_dp->mst_mgr, | 165 | ret = drm_dp_mst_allocate_vcpi(&intel_dp->mst_mgr, |
167 | connector->port, | 166 | connector->port, |
168 | pipe_config->pbn, &slots); | 167 | pipe_config->pbn, |
168 | pipe_config->dp_m_n.tu); | ||
169 | if (ret == false) { | 169 | if (ret == false) { |
170 | DRM_ERROR("failed to allocate vcpi\n"); | 170 | DRM_ERROR("failed to allocate vcpi\n"); |
171 | return; | 171 | return; |
diff --git a/drivers/gpu/drm/msm/mdp/mdp5/mdp5_plane.c b/drivers/gpu/drm/msm/mdp/mdp5/mdp5_plane.c index 0ffb8affef35..60a5451ae0b9 100644 --- a/drivers/gpu/drm/msm/mdp/mdp5/mdp5_plane.c +++ b/drivers/gpu/drm/msm/mdp/mdp5/mdp5_plane.c | |||
@@ -37,7 +37,8 @@ static int mdp5_update_cursor_plane_legacy(struct drm_plane *plane, | |||
37 | int crtc_x, int crtc_y, | 37 | int crtc_x, int crtc_y, |
38 | unsigned int crtc_w, unsigned int crtc_h, | 38 | unsigned int crtc_w, unsigned int crtc_h, |
39 | uint32_t src_x, uint32_t src_y, | 39 | uint32_t src_x, uint32_t src_y, |
40 | uint32_t src_w, uint32_t src_h); | 40 | uint32_t src_w, uint32_t src_h, |
41 | struct drm_modeset_acquire_ctx *ctx); | ||
41 | 42 | ||
42 | static void set_scanout_locked(struct drm_plane *plane, | 43 | static void set_scanout_locked(struct drm_plane *plane, |
43 | struct drm_framebuffer *fb); | 44 | struct drm_framebuffer *fb); |
@@ -886,7 +887,8 @@ static int mdp5_update_cursor_plane_legacy(struct drm_plane *plane, | |||
886 | int crtc_x, int crtc_y, | 887 | int crtc_x, int crtc_y, |
887 | unsigned int crtc_w, unsigned int crtc_h, | 888 | unsigned int crtc_w, unsigned int crtc_h, |
888 | uint32_t src_x, uint32_t src_y, | 889 | uint32_t src_x, uint32_t src_y, |
889 | uint32_t src_w, uint32_t src_h) | 890 | uint32_t src_w, uint32_t src_h, |
891 | struct drm_modeset_acquire_ctx *ctx) | ||
890 | { | 892 | { |
891 | struct drm_plane_state *plane_state, *new_plane_state; | 893 | struct drm_plane_state *plane_state, *new_plane_state; |
892 | struct mdp5_plane_state *mdp5_pstate; | 894 | struct mdp5_plane_state *mdp5_pstate; |
@@ -954,7 +956,7 @@ slow_free: | |||
954 | slow: | 956 | slow: |
955 | return drm_atomic_helper_update_plane(plane, crtc, fb, | 957 | return drm_atomic_helper_update_plane(plane, crtc, fb, |
956 | crtc_x, crtc_y, crtc_w, crtc_h, | 958 | crtc_x, crtc_y, crtc_w, crtc_h, |
957 | src_x, src_y, src_w, src_h); | 959 | src_x, src_y, src_w, src_h, ctx); |
958 | } | 960 | } |
959 | 961 | ||
960 | enum mdp5_pipe mdp5_plane_pipe(struct drm_plane *plane) | 962 | enum mdp5_pipe mdp5_plane_pipe(struct drm_plane *plane) |
diff --git a/drivers/gpu/drm/nouveau/dispnv04/crtc.c b/drivers/gpu/drm/nouveau/dispnv04/crtc.c index ab7b69c11d40..43ab560de7f9 100644 --- a/drivers/gpu/drm/nouveau/dispnv04/crtc.c +++ b/drivers/gpu/drm/nouveau/dispnv04/crtc.c | |||
@@ -1031,8 +1031,9 @@ nv04_crtc_cursor_move(struct drm_crtc *crtc, int x, int y) | |||
1031 | return 0; | 1031 | return 0; |
1032 | } | 1032 | } |
1033 | 1033 | ||
1034 | int | 1034 | static int |
1035 | nouveau_crtc_set_config(struct drm_mode_set *set) | 1035 | nouveau_crtc_set_config(struct drm_mode_set *set, |
1036 | struct drm_modeset_acquire_ctx *ctx) | ||
1036 | { | 1037 | { |
1037 | struct drm_device *dev; | 1038 | struct drm_device *dev; |
1038 | struct nouveau_drm *drm; | 1039 | struct nouveau_drm *drm; |
@@ -1049,7 +1050,7 @@ nouveau_crtc_set_config(struct drm_mode_set *set) | |||
1049 | if (ret < 0 && ret != -EACCES) | 1050 | if (ret < 0 && ret != -EACCES) |
1050 | return ret; | 1051 | return ret; |
1051 | 1052 | ||
1052 | ret = drm_crtc_helper_set_config(set); | 1053 | ret = drm_crtc_helper_set_config(set, ctx); |
1053 | 1054 | ||
1054 | drm = nouveau_drm(dev); | 1055 | drm = nouveau_drm(dev); |
1055 | 1056 | ||
diff --git a/drivers/gpu/drm/nouveau/dispnv04/overlay.c b/drivers/gpu/drm/nouveau/dispnv04/overlay.c index 5319f2a7f24d..e54944d23268 100644 --- a/drivers/gpu/drm/nouveau/dispnv04/overlay.c +++ b/drivers/gpu/drm/nouveau/dispnv04/overlay.c | |||
@@ -94,7 +94,8 @@ nv10_update_plane(struct drm_plane *plane, struct drm_crtc *crtc, | |||
94 | struct drm_framebuffer *fb, int crtc_x, int crtc_y, | 94 | struct drm_framebuffer *fb, int crtc_x, int crtc_y, |
95 | unsigned int crtc_w, unsigned int crtc_h, | 95 | unsigned int crtc_w, unsigned int crtc_h, |
96 | uint32_t src_x, uint32_t src_y, | 96 | uint32_t src_x, uint32_t src_y, |
97 | uint32_t src_w, uint32_t src_h) | 97 | uint32_t src_w, uint32_t src_h, |
98 | struct drm_modeset_acquire_ctx *ctx) | ||
98 | { | 99 | { |
99 | struct nouveau_drm *drm = nouveau_drm(plane->dev); | 100 | struct nouveau_drm *drm = nouveau_drm(plane->dev); |
100 | struct nvif_object *dev = &drm->client.device.object; | 101 | struct nvif_object *dev = &drm->client.device.object; |
@@ -172,7 +173,8 @@ nv10_update_plane(struct drm_plane *plane, struct drm_crtc *crtc, | |||
172 | } | 173 | } |
173 | 174 | ||
174 | static int | 175 | static int |
175 | nv10_disable_plane(struct drm_plane *plane) | 176 | nv10_disable_plane(struct drm_plane *plane, |
177 | struct drm_modeset_acquire_ctx *ctx) | ||
176 | { | 178 | { |
177 | struct nvif_object *dev = &nouveau_drm(plane->dev)->client.device.object; | 179 | struct nvif_object *dev = &nouveau_drm(plane->dev)->client.device.object; |
178 | struct nouveau_plane *nv_plane = | 180 | struct nouveau_plane *nv_plane = |
@@ -190,7 +192,7 @@ nv10_disable_plane(struct drm_plane *plane) | |||
190 | static void | 192 | static void |
191 | nv_destroy_plane(struct drm_plane *plane) | 193 | nv_destroy_plane(struct drm_plane *plane) |
192 | { | 194 | { |
193 | plane->funcs->disable_plane(plane); | 195 | drm_plane_force_disable(plane); |
194 | drm_plane_cleanup(plane); | 196 | drm_plane_cleanup(plane); |
195 | kfree(plane); | 197 | kfree(plane); |
196 | } | 198 | } |
@@ -331,7 +333,7 @@ nv10_overlay_init(struct drm_device *device) | |||
331 | 333 | ||
332 | plane->set_params = nv10_set_params; | 334 | plane->set_params = nv10_set_params; |
333 | nv10_set_params(plane); | 335 | nv10_set_params(plane); |
334 | nv10_disable_plane(&plane->base); | 336 | drm_plane_force_disable(&plane->base); |
335 | return; | 337 | return; |
336 | cleanup: | 338 | cleanup: |
337 | drm_plane_cleanup(&plane->base); | 339 | drm_plane_cleanup(&plane->base); |
@@ -345,7 +347,8 @@ nv04_update_plane(struct drm_plane *plane, struct drm_crtc *crtc, | |||
345 | struct drm_framebuffer *fb, int crtc_x, int crtc_y, | 347 | struct drm_framebuffer *fb, int crtc_x, int crtc_y, |
346 | unsigned int crtc_w, unsigned int crtc_h, | 348 | unsigned int crtc_w, unsigned int crtc_h, |
347 | uint32_t src_x, uint32_t src_y, | 349 | uint32_t src_x, uint32_t src_y, |
348 | uint32_t src_w, uint32_t src_h) | 350 | uint32_t src_w, uint32_t src_h, |
351 | struct drm_modeset_acquire_ctx *ctx) | ||
349 | { | 352 | { |
350 | struct nvif_object *dev = &nouveau_drm(plane->dev)->client.device.object; | 353 | struct nvif_object *dev = &nouveau_drm(plane->dev)->client.device.object; |
351 | struct nouveau_plane *nv_plane = | 354 | struct nouveau_plane *nv_plane = |
@@ -425,7 +428,8 @@ nv04_update_plane(struct drm_plane *plane, struct drm_crtc *crtc, | |||
425 | } | 428 | } |
426 | 429 | ||
427 | static int | 430 | static int |
428 | nv04_disable_plane(struct drm_plane *plane) | 431 | nv04_disable_plane(struct drm_plane *plane, |
432 | struct drm_modeset_acquire_ctx *ctx) | ||
429 | { | 433 | { |
430 | struct nvif_object *dev = &nouveau_drm(plane->dev)->client.device.object; | 434 | struct nvif_object *dev = &nouveau_drm(plane->dev)->client.device.object; |
431 | struct nouveau_plane *nv_plane = | 435 | struct nouveau_plane *nv_plane = |
@@ -483,7 +487,7 @@ nv04_overlay_init(struct drm_device *device) | |||
483 | drm_object_attach_property(&plane->base.base, | 487 | drm_object_attach_property(&plane->base.base, |
484 | plane->props.brightness, plane->brightness); | 488 | plane->props.brightness, plane->brightness); |
485 | 489 | ||
486 | nv04_disable_plane(&plane->base); | 490 | drm_plane_force_disable(&plane->base); |
487 | return; | 491 | return; |
488 | cleanup: | 492 | cleanup: |
489 | drm_plane_cleanup(&plane->base); | 493 | drm_plane_cleanup(&plane->base); |
diff --git a/drivers/gpu/drm/nouveau/nouveau_display.c b/drivers/gpu/drm/nouveau/nouveau_display.c index 33269c7df30f..6104f61b00fc 100644 --- a/drivers/gpu/drm/nouveau/nouveau_display.c +++ b/drivers/gpu/drm/nouveau/nouveau_display.c | |||
@@ -436,8 +436,12 @@ nouveau_display_fini(struct drm_device *dev, bool suspend) | |||
436 | struct drm_connector *connector; | 436 | struct drm_connector *connector; |
437 | struct drm_crtc *crtc; | 437 | struct drm_crtc *crtc; |
438 | 438 | ||
439 | if (!suspend) | 439 | if (!suspend) { |
440 | drm_crtc_force_disable_all(dev); | 440 | if (drm_drv_uses_atomic_modeset(dev)) |
441 | drm_atomic_helper_shutdown(dev); | ||
442 | else | ||
443 | drm_crtc_force_disable_all(dev); | ||
444 | } | ||
441 | 445 | ||
442 | /* Make sure that drm and hw vblank irqs get properly disabled. */ | 446 | /* Make sure that drm and hw vblank irqs get properly disabled. */ |
443 | drm_for_each_crtc(crtc, dev) | 447 | drm_for_each_crtc(crtc, dev) |
@@ -788,7 +792,8 @@ fail: | |||
788 | 792 | ||
789 | int | 793 | int |
790 | nouveau_crtc_page_flip(struct drm_crtc *crtc, struct drm_framebuffer *fb, | 794 | nouveau_crtc_page_flip(struct drm_crtc *crtc, struct drm_framebuffer *fb, |
791 | struct drm_pending_vblank_event *event, u32 flags) | 795 | struct drm_pending_vblank_event *event, u32 flags, |
796 | struct drm_modeset_acquire_ctx *ctx) | ||
792 | { | 797 | { |
793 | const int swap_interval = (flags & DRM_MODE_PAGE_FLIP_ASYNC) ? 0 : 1; | 798 | const int swap_interval = (flags & DRM_MODE_PAGE_FLIP_ASYNC) ? 0 : 1; |
794 | struct drm_device *dev = crtc->dev; | 799 | struct drm_device *dev = crtc->dev; |
diff --git a/drivers/gpu/drm/nouveau/nouveau_display.h b/drivers/gpu/drm/nouveau/nouveau_display.h index 4a75df06c139..e1d772d39488 100644 --- a/drivers/gpu/drm/nouveau/nouveau_display.h +++ b/drivers/gpu/drm/nouveau/nouveau_display.h | |||
@@ -76,7 +76,8 @@ int nouveau_display_vblstamp(struct drm_device *, unsigned int, int *, | |||
76 | 76 | ||
77 | int nouveau_crtc_page_flip(struct drm_crtc *crtc, struct drm_framebuffer *fb, | 77 | int nouveau_crtc_page_flip(struct drm_crtc *crtc, struct drm_framebuffer *fb, |
78 | struct drm_pending_vblank_event *event, | 78 | struct drm_pending_vblank_event *event, |
79 | uint32_t page_flip_flags); | 79 | uint32_t page_flip_flags, |
80 | struct drm_modeset_acquire_ctx *ctx); | ||
80 | int nouveau_finish_page_flip(struct nouveau_channel *, | 81 | int nouveau_finish_page_flip(struct nouveau_channel *, |
81 | struct nouveau_page_flip_state *); | 82 | struct nouveau_page_flip_state *); |
82 | 83 | ||
@@ -87,7 +88,6 @@ int nouveau_display_dumb_map_offset(struct drm_file *, struct drm_device *, | |||
87 | 88 | ||
88 | void nouveau_hdmi_mode_set(struct drm_encoder *, struct drm_display_mode *); | 89 | void nouveau_hdmi_mode_set(struct drm_encoder *, struct drm_display_mode *); |
89 | 90 | ||
90 | int nouveau_crtc_set_config(struct drm_mode_set *set); | ||
91 | #ifdef CONFIG_DRM_NOUVEAU_BACKLIGHT | 91 | #ifdef CONFIG_DRM_NOUVEAU_BACKLIGHT |
92 | extern int nouveau_backlight_init(struct drm_device *); | 92 | extern int nouveau_backlight_init(struct drm_device *); |
93 | extern void nouveau_backlight_exit(struct drm_device *); | 93 | extern void nouveau_backlight_exit(struct drm_device *); |
diff --git a/drivers/gpu/drm/nouveau/nouveau_vga.c b/drivers/gpu/drm/nouveau/nouveau_vga.c index ccb597eac538..a4aacbc0cec8 100644 --- a/drivers/gpu/drm/nouveau/nouveau_vga.c +++ b/drivers/gpu/drm/nouveau/nouveau_vga.c | |||
@@ -95,6 +95,10 @@ nouveau_vga_init(struct nouveau_drm *drm) | |||
95 | 95 | ||
96 | vga_client_register(dev->pdev, dev, NULL, nouveau_vga_set_decode); | 96 | vga_client_register(dev->pdev, dev, NULL, nouveau_vga_set_decode); |
97 | 97 | ||
98 | /* don't register Thunderbolt eGPU with vga_switcheroo */ | ||
99 | if (pci_is_thunderbolt_attached(dev->pdev)) | ||
100 | return; | ||
101 | |||
98 | if (nouveau_runtime_pm == 1) | 102 | if (nouveau_runtime_pm == 1) |
99 | runtime = true; | 103 | runtime = true; |
100 | if ((nouveau_runtime_pm == -1) && (nouveau_is_optimus() || nouveau_is_v1_dsm())) | 104 | if ((nouveau_runtime_pm == -1) && (nouveau_is_optimus() || nouveau_is_v1_dsm())) |
@@ -111,6 +115,11 @@ nouveau_vga_fini(struct nouveau_drm *drm) | |||
111 | struct drm_device *dev = drm->dev; | 115 | struct drm_device *dev = drm->dev; |
112 | bool runtime = false; | 116 | bool runtime = false; |
113 | 117 | ||
118 | vga_client_register(dev->pdev, NULL, NULL, NULL); | ||
119 | |||
120 | if (pci_is_thunderbolt_attached(dev->pdev)) | ||
121 | return; | ||
122 | |||
114 | if (nouveau_runtime_pm == 1) | 123 | if (nouveau_runtime_pm == 1) |
115 | runtime = true; | 124 | runtime = true; |
116 | if ((nouveau_runtime_pm == -1) && (nouveau_is_optimus() || nouveau_is_v1_dsm())) | 125 | if ((nouveau_runtime_pm == -1) && (nouveau_is_optimus() || nouveau_is_v1_dsm())) |
@@ -119,7 +128,6 @@ nouveau_vga_fini(struct nouveau_drm *drm) | |||
119 | vga_switcheroo_unregister_client(dev->pdev); | 128 | vga_switcheroo_unregister_client(dev->pdev); |
120 | if (runtime && nouveau_is_v1_dsm() && !nouveau_is_optimus()) | 129 | if (runtime && nouveau_is_v1_dsm() && !nouveau_is_optimus()) |
121 | vga_switcheroo_fini_domain_pm_ops(drm->dev->dev); | 130 | vga_switcheroo_fini_domain_pm_ops(drm->dev->dev); |
122 | vga_client_register(dev->pdev, NULL, NULL, NULL); | ||
123 | } | 131 | } |
124 | 132 | ||
125 | 133 | ||
diff --git a/drivers/gpu/drm/nouveau/nv50_display.c b/drivers/gpu/drm/nouveau/nv50_display.c index 7ad1ee580cf0..418872b493a3 100644 --- a/drivers/gpu/drm/nouveau/nv50_display.c +++ b/drivers/gpu/drm/nouveau/nv50_display.c | |||
@@ -2895,7 +2895,8 @@ nv50_msto_enable(struct drm_encoder *encoder) | |||
2895 | if (WARN_ON(!mstc)) | 2895 | if (WARN_ON(!mstc)) |
2896 | return; | 2896 | return; |
2897 | 2897 | ||
2898 | r = drm_dp_mst_allocate_vcpi(&mstm->mgr, mstc->port, mstc->pbn, &slots); | 2898 | slots = drm_dp_find_vcpi_slots(&mstm->mgr, mstc->pbn); |
2899 | r = drm_dp_mst_allocate_vcpi(&mstm->mgr, mstc->port, mstc->pbn, slots); | ||
2899 | WARN_ON(!r); | 2900 | WARN_ON(!r); |
2900 | 2901 | ||
2901 | if (mstm->outp->dcb->sorconf.link & 1) | 2902 | if (mstm->outp->dcb->sorconf.link & 1) |
diff --git a/drivers/gpu/drm/radeon/radeon_device.c b/drivers/gpu/drm/radeon/radeon_device.c index 64b02f3c7906..6ecf42783d4b 100644 --- a/drivers/gpu/drm/radeon/radeon_device.c +++ b/drivers/gpu/drm/radeon/radeon_device.c | |||
@@ -1468,7 +1468,9 @@ int radeon_device_init(struct radeon_device *rdev, | |||
1468 | 1468 | ||
1469 | if (rdev->flags & RADEON_IS_PX) | 1469 | if (rdev->flags & RADEON_IS_PX) |
1470 | runtime = true; | 1470 | runtime = true; |
1471 | vga_switcheroo_register_client(rdev->pdev, &radeon_switcheroo_ops, runtime); | 1471 | if (!pci_is_thunderbolt_attached(rdev->pdev)) |
1472 | vga_switcheroo_register_client(rdev->pdev, | ||
1473 | &radeon_switcheroo_ops, runtime); | ||
1472 | if (runtime) | 1474 | if (runtime) |
1473 | vga_switcheroo_init_domain_pm_ops(rdev->dev, &rdev->vga_pm_domain); | 1475 | vga_switcheroo_init_domain_pm_ops(rdev->dev, &rdev->vga_pm_domain); |
1474 | 1476 | ||
@@ -1561,7 +1563,8 @@ void radeon_device_fini(struct radeon_device *rdev) | |||
1561 | /* evict vram memory */ | 1563 | /* evict vram memory */ |
1562 | radeon_bo_evict_vram(rdev); | 1564 | radeon_bo_evict_vram(rdev); |
1563 | radeon_fini(rdev); | 1565 | radeon_fini(rdev); |
1564 | vga_switcheroo_unregister_client(rdev->pdev); | 1566 | if (!pci_is_thunderbolt_attached(rdev->pdev)) |
1567 | vga_switcheroo_unregister_client(rdev->pdev); | ||
1565 | if (rdev->flags & RADEON_IS_PX) | 1568 | if (rdev->flags & RADEON_IS_PX) |
1566 | vga_switcheroo_fini_domain_pm_ops(rdev->dev); | 1569 | vga_switcheroo_fini_domain_pm_ops(rdev->dev); |
1567 | vga_client_register(rdev->pdev, NULL, NULL, NULL); | 1570 | vga_client_register(rdev->pdev, NULL, NULL, NULL); |
diff --git a/drivers/gpu/drm/radeon/radeon_display.c b/drivers/gpu/drm/radeon/radeon_display.c index aea8b62835a4..146297a702ab 100644 --- a/drivers/gpu/drm/radeon/radeon_display.c +++ b/drivers/gpu/drm/radeon/radeon_display.c | |||
@@ -485,7 +485,8 @@ static int radeon_crtc_page_flip_target(struct drm_crtc *crtc, | |||
485 | struct drm_framebuffer *fb, | 485 | struct drm_framebuffer *fb, |
486 | struct drm_pending_vblank_event *event, | 486 | struct drm_pending_vblank_event *event, |
487 | uint32_t page_flip_flags, | 487 | uint32_t page_flip_flags, |
488 | uint32_t target) | 488 | uint32_t target, |
489 | struct drm_modeset_acquire_ctx *ctx) | ||
489 | { | 490 | { |
490 | struct drm_device *dev = crtc->dev; | 491 | struct drm_device *dev = crtc->dev; |
491 | struct radeon_device *rdev = dev->dev_private; | 492 | struct radeon_device *rdev = dev->dev_private; |
@@ -623,7 +624,8 @@ cleanup: | |||
623 | } | 624 | } |
624 | 625 | ||
625 | static int | 626 | static int |
626 | radeon_crtc_set_config(struct drm_mode_set *set) | 627 | radeon_crtc_set_config(struct drm_mode_set *set, |
628 | struct drm_modeset_acquire_ctx *ctx) | ||
627 | { | 629 | { |
628 | struct drm_device *dev; | 630 | struct drm_device *dev; |
629 | struct radeon_device *rdev; | 631 | struct radeon_device *rdev; |
@@ -640,7 +642,7 @@ radeon_crtc_set_config(struct drm_mode_set *set) | |||
640 | if (ret < 0) | 642 | if (ret < 0) |
641 | return ret; | 643 | return ret; |
642 | 644 | ||
643 | ret = drm_crtc_helper_set_config(set); | 645 | ret = drm_crtc_helper_set_config(set, ctx); |
644 | 646 | ||
645 | list_for_each_entry(crtc, &dev->mode_config.crtc_list, head) | 647 | list_for_each_entry(crtc, &dev->mode_config.crtc_list, head) |
646 | if (crtc->enabled) | 648 | if (crtc->enabled) |
diff --git a/drivers/gpu/drm/radeon/radeon_dp_mst.c b/drivers/gpu/drm/radeon/radeon_dp_mst.c index 7d5ada3980dc..6598306dca9b 100644 --- a/drivers/gpu/drm/radeon/radeon_dp_mst.c +++ b/drivers/gpu/drm/radeon/radeon_dp_mst.c | |||
@@ -453,9 +453,11 @@ radeon_mst_encoder_dpms(struct drm_encoder *encoder, int mode) | |||
453 | DRM_DEBUG_KMS("dig encoder is %d %d %d\n", dig_enc->dig_encoder, | 453 | DRM_DEBUG_KMS("dig encoder is %d %d %d\n", dig_enc->dig_encoder, |
454 | dig_enc->linkb, radeon_crtc->crtc_id); | 454 | dig_enc->linkb, radeon_crtc->crtc_id); |
455 | 455 | ||
456 | slots = drm_dp_find_vcpi_slots(&radeon_connector->mst_port->mst_mgr, | ||
457 | mst_enc->pbn); | ||
456 | ret = drm_dp_mst_allocate_vcpi(&radeon_connector->mst_port->mst_mgr, | 458 | ret = drm_dp_mst_allocate_vcpi(&radeon_connector->mst_port->mst_mgr, |
457 | radeon_connector->port, | 459 | radeon_connector->port, |
458 | mst_enc->pbn, &slots); | 460 | mst_enc->pbn, slots); |
459 | ret = drm_dp_update_payload_part1(&radeon_connector->mst_port->mst_mgr); | 461 | ret = drm_dp_update_payload_part1(&radeon_connector->mst_port->mst_mgr); |
460 | 462 | ||
461 | radeon_dp_mst_set_be_cntl(primary, mst_enc, | 463 | radeon_dp_mst_set_be_cntl(primary, mst_enc, |
diff --git a/drivers/gpu/drm/radeon/radeon_kms.c b/drivers/gpu/drm/radeon/radeon_kms.c index a32a62e03a44..e3e7cb1d10a2 100644 --- a/drivers/gpu/drm/radeon/radeon_kms.c +++ b/drivers/gpu/drm/radeon/radeon_kms.c | |||
@@ -115,7 +115,8 @@ int radeon_driver_load_kms(struct drm_device *dev, unsigned long flags) | |||
115 | 115 | ||
116 | if ((radeon_runtime_pm != 0) && | 116 | if ((radeon_runtime_pm != 0) && |
117 | radeon_has_atpx() && | 117 | radeon_has_atpx() && |
118 | ((flags & RADEON_IS_IGP) == 0)) | 118 | ((flags & RADEON_IS_IGP) == 0) && |
119 | !pci_is_thunderbolt_attached(rdev->pdev)) | ||
119 | flags |= RADEON_IS_PX; | 120 | flags |= RADEON_IS_PX; |
120 | 121 | ||
121 | /* radeon_device_init should report only fatal error | 122 | /* radeon_device_init should report only fatal error |
diff --git a/drivers/gpu/drm/rockchip/Kconfig b/drivers/gpu/drm/rockchip/Kconfig index 0e4eb845cbb0..50c41c0a50ef 100644 --- a/drivers/gpu/drm/rockchip/Kconfig +++ b/drivers/gpu/drm/rockchip/Kconfig | |||
@@ -13,7 +13,7 @@ config DRM_ROCKCHIP | |||
13 | IP found on the SoC. | 13 | IP found on the SoC. |
14 | 14 | ||
15 | config ROCKCHIP_ANALOGIX_DP | 15 | config ROCKCHIP_ANALOGIX_DP |
16 | tristate "Rockchip specific extensions for Analogix DP driver" | 16 | bool "Rockchip specific extensions for Analogix DP driver" |
17 | depends on DRM_ROCKCHIP | 17 | depends on DRM_ROCKCHIP |
18 | select DRM_ANALOGIX_DP | 18 | select DRM_ANALOGIX_DP |
19 | help | 19 | help |
@@ -22,7 +22,7 @@ config ROCKCHIP_ANALOGIX_DP | |||
22 | on RK3288 based SoC, you should selet this option. | 22 | on RK3288 based SoC, you should selet this option. |
23 | 23 | ||
24 | config ROCKCHIP_CDN_DP | 24 | config ROCKCHIP_CDN_DP |
25 | tristate "Rockchip cdn DP" | 25 | bool "Rockchip cdn DP" |
26 | depends on DRM_ROCKCHIP | 26 | depends on DRM_ROCKCHIP |
27 | depends on EXTCON | 27 | depends on EXTCON |
28 | select SND_SOC_HDMI_CODEC if SND_SOC | 28 | select SND_SOC_HDMI_CODEC if SND_SOC |
@@ -33,7 +33,7 @@ config ROCKCHIP_CDN_DP | |||
33 | option. | 33 | option. |
34 | 34 | ||
35 | config ROCKCHIP_DW_HDMI | 35 | config ROCKCHIP_DW_HDMI |
36 | tristate "Rockchip specific extensions for Synopsys DW HDMI" | 36 | bool "Rockchip specific extensions for Synopsys DW HDMI" |
37 | depends on DRM_ROCKCHIP | 37 | depends on DRM_ROCKCHIP |
38 | select DRM_DW_HDMI | 38 | select DRM_DW_HDMI |
39 | help | 39 | help |
@@ -43,7 +43,7 @@ config ROCKCHIP_DW_HDMI | |||
43 | option. | 43 | option. |
44 | 44 | ||
45 | config ROCKCHIP_DW_MIPI_DSI | 45 | config ROCKCHIP_DW_MIPI_DSI |
46 | tristate "Rockchip specific extensions for Synopsys DW MIPI DSI" | 46 | bool "Rockchip specific extensions for Synopsys DW MIPI DSI" |
47 | depends on DRM_ROCKCHIP | 47 | depends on DRM_ROCKCHIP |
48 | select DRM_MIPI_DSI | 48 | select DRM_MIPI_DSI |
49 | help | 49 | help |
@@ -53,7 +53,7 @@ config ROCKCHIP_DW_MIPI_DSI | |||
53 | option. | 53 | option. |
54 | 54 | ||
55 | config ROCKCHIP_INNO_HDMI | 55 | config ROCKCHIP_INNO_HDMI |
56 | tristate "Rockchip specific extensions for Innosilicon HDMI" | 56 | bool "Rockchip specific extensions for Innosilicon HDMI" |
57 | depends on DRM_ROCKCHIP | 57 | depends on DRM_ROCKCHIP |
58 | help | 58 | help |
59 | This selects support for Rockchip SoC specific extensions | 59 | This selects support for Rockchip SoC specific extensions |
diff --git a/drivers/gpu/drm/rockchip/Makefile b/drivers/gpu/drm/rockchip/Makefile index c931e2a7d8de..fa8dc9d9aac2 100644 --- a/drivers/gpu/drm/rockchip/Makefile +++ b/drivers/gpu/drm/rockchip/Makefile | |||
@@ -3,14 +3,14 @@ | |||
3 | # Direct Rendering Infrastructure (DRI) in XFree86 4.1.0 and higher. | 3 | # Direct Rendering Infrastructure (DRI) in XFree86 4.1.0 and higher. |
4 | 4 | ||
5 | rockchipdrm-y := rockchip_drm_drv.o rockchip_drm_fb.o \ | 5 | rockchipdrm-y := rockchip_drm_drv.o rockchip_drm_fb.o \ |
6 | rockchip_drm_gem.o rockchip_drm_psr.o rockchip_drm_vop.o | 6 | rockchip_drm_gem.o rockchip_drm_psr.o \ |
7 | rockchip_drm_vop.o rockchip_vop_reg.o | ||
7 | rockchipdrm-$(CONFIG_DRM_FBDEV_EMULATION) += rockchip_drm_fbdev.o | 8 | rockchipdrm-$(CONFIG_DRM_FBDEV_EMULATION) += rockchip_drm_fbdev.o |
8 | 9 | ||
9 | obj-$(CONFIG_ROCKCHIP_ANALOGIX_DP) += analogix_dp-rockchip.o | 10 | rockchipdrm-$(CONFIG_ROCKCHIP_ANALOGIX_DP) += analogix_dp-rockchip.o |
10 | obj-$(CONFIG_ROCKCHIP_CDN_DP) += cdn-dp.o | 11 | rockchipdrm-$(CONFIG_ROCKCHIP_CDN_DP) += cdn-dp-core.o cdn-dp-reg.o |
11 | cdn-dp-objs := cdn-dp-core.o cdn-dp-reg.o | 12 | rockchipdrm-$(CONFIG_ROCKCHIP_DW_HDMI) += dw_hdmi-rockchip.o |
12 | obj-$(CONFIG_ROCKCHIP_DW_HDMI) += dw_hdmi-rockchip.o | 13 | rockchipdrm-$(CONFIG_ROCKCHIP_DW_MIPI_DSI) += dw-mipi-dsi.o |
13 | obj-$(CONFIG_ROCKCHIP_DW_MIPI_DSI) += dw-mipi-dsi.o | 14 | rockchipdrm-$(CONFIG_ROCKCHIP_INNO_HDMI) += inno_hdmi.o |
14 | obj-$(CONFIG_ROCKCHIP_INNO_HDMI) += inno_hdmi.o | ||
15 | 15 | ||
16 | obj-$(CONFIG_DRM_ROCKCHIP) += rockchipdrm.o rockchip_vop_reg.o | 16 | obj-$(CONFIG_DRM_ROCKCHIP) += rockchipdrm.o |
diff --git a/drivers/gpu/drm/rockchip/analogix_dp-rockchip.c b/drivers/gpu/drm/rockchip/analogix_dp-rockchip.c index 8548e8271639..91ebe5c2c7a0 100644 --- a/drivers/gpu/drm/rockchip/analogix_dp-rockchip.c +++ b/drivers/gpu/drm/rockchip/analogix_dp-rockchip.c | |||
@@ -507,7 +507,7 @@ static const struct of_device_id rockchip_dp_dt_ids[] = { | |||
507 | }; | 507 | }; |
508 | MODULE_DEVICE_TABLE(of, rockchip_dp_dt_ids); | 508 | MODULE_DEVICE_TABLE(of, rockchip_dp_dt_ids); |
509 | 509 | ||
510 | static struct platform_driver rockchip_dp_driver = { | 510 | struct platform_driver rockchip_dp_driver = { |
511 | .probe = rockchip_dp_probe, | 511 | .probe = rockchip_dp_probe, |
512 | .remove = rockchip_dp_remove, | 512 | .remove = rockchip_dp_remove, |
513 | .driver = { | 513 | .driver = { |
@@ -516,10 +516,3 @@ static struct platform_driver rockchip_dp_driver = { | |||
516 | .of_match_table = of_match_ptr(rockchip_dp_dt_ids), | 516 | .of_match_table = of_match_ptr(rockchip_dp_dt_ids), |
517 | }, | 517 | }, |
518 | }; | 518 | }; |
519 | |||
520 | module_platform_driver(rockchip_dp_driver); | ||
521 | |||
522 | MODULE_AUTHOR("Yakir Yang <ykk@rock-chips.com>"); | ||
523 | MODULE_AUTHOR("Jeff chen <jeff.chen@rock-chips.com>"); | ||
524 | MODULE_DESCRIPTION("Rockchip Specific Analogix-DP Driver Extension"); | ||
525 | MODULE_LICENSE("GPL v2"); | ||
diff --git a/drivers/gpu/drm/rockchip/cdn-dp-core.c b/drivers/gpu/drm/rockchip/cdn-dp-core.c index 9edb8dc1ea14..4e55d63c3ef3 100644 --- a/drivers/gpu/drm/rockchip/cdn-dp-core.c +++ b/drivers/gpu/drm/rockchip/cdn-dp-core.c | |||
@@ -1244,7 +1244,7 @@ static const struct dev_pm_ops cdn_dp_pm_ops = { | |||
1244 | cdn_dp_resume) | 1244 | cdn_dp_resume) |
1245 | }; | 1245 | }; |
1246 | 1246 | ||
1247 | static struct platform_driver cdn_dp_driver = { | 1247 | struct platform_driver cdn_dp_driver = { |
1248 | .probe = cdn_dp_probe, | 1248 | .probe = cdn_dp_probe, |
1249 | .remove = cdn_dp_remove, | 1249 | .remove = cdn_dp_remove, |
1250 | .shutdown = cdn_dp_shutdown, | 1250 | .shutdown = cdn_dp_shutdown, |
@@ -1255,9 +1255,3 @@ static struct platform_driver cdn_dp_driver = { | |||
1255 | .pm = &cdn_dp_pm_ops, | 1255 | .pm = &cdn_dp_pm_ops, |
1256 | }, | 1256 | }, |
1257 | }; | 1257 | }; |
1258 | |||
1259 | module_platform_driver(cdn_dp_driver); | ||
1260 | |||
1261 | MODULE_AUTHOR("Chris Zhong <zyw@rock-chips.com>"); | ||
1262 | MODULE_DESCRIPTION("cdn DP Driver"); | ||
1263 | MODULE_LICENSE("GPL v2"); | ||
diff --git a/drivers/gpu/drm/rockchip/dw-mipi-dsi.c b/drivers/gpu/drm/rockchip/dw-mipi-dsi.c index f84f9ae2fd35..21b9737662ae 100644 --- a/drivers/gpu/drm/rockchip/dw-mipi-dsi.c +++ b/drivers/gpu/drm/rockchip/dw-mipi-dsi.c | |||
@@ -34,7 +34,7 @@ | |||
34 | #define RK3288_DSI0_SEL_VOP_LIT BIT(6) | 34 | #define RK3288_DSI0_SEL_VOP_LIT BIT(6) |
35 | #define RK3288_DSI1_SEL_VOP_LIT BIT(9) | 35 | #define RK3288_DSI1_SEL_VOP_LIT BIT(9) |
36 | 36 | ||
37 | #define RK3399_GRF_SOC_CON19 0x6250 | 37 | #define RK3399_GRF_SOC_CON20 0x6250 |
38 | #define RK3399_DSI0_SEL_VOP_LIT BIT(0) | 38 | #define RK3399_DSI0_SEL_VOP_LIT BIT(0) |
39 | #define RK3399_DSI1_SEL_VOP_LIT BIT(4) | 39 | #define RK3399_DSI1_SEL_VOP_LIT BIT(4) |
40 | 40 | ||
@@ -251,6 +251,9 @@ | |||
251 | #define THS_PRE_PROGRAM_EN BIT(7) | 251 | #define THS_PRE_PROGRAM_EN BIT(7) |
252 | #define THS_ZERO_PROGRAM_EN BIT(6) | 252 | #define THS_ZERO_PROGRAM_EN BIT(6) |
253 | 253 | ||
254 | #define DW_MIPI_NEEDS_PHY_CFG_CLK BIT(0) | ||
255 | #define DW_MIPI_NEEDS_GRF_CLK BIT(1) | ||
256 | |||
254 | enum { | 257 | enum { |
255 | BANDGAP_97_07, | 258 | BANDGAP_97_07, |
256 | BANDGAP_98_05, | 259 | BANDGAP_98_05, |
@@ -279,6 +282,7 @@ struct dw_mipi_dsi_plat_data { | |||
279 | u32 grf_switch_reg; | 282 | u32 grf_switch_reg; |
280 | u32 grf_dsi0_mode; | 283 | u32 grf_dsi0_mode; |
281 | u32 grf_dsi0_mode_reg; | 284 | u32 grf_dsi0_mode_reg; |
285 | unsigned int flags; | ||
282 | unsigned int max_data_lanes; | 286 | unsigned int max_data_lanes; |
283 | }; | 287 | }; |
284 | 288 | ||
@@ -291,6 +295,7 @@ struct dw_mipi_dsi { | |||
291 | struct regmap *grf_regmap; | 295 | struct regmap *grf_regmap; |
292 | void __iomem *base; | 296 | void __iomem *base; |
293 | 297 | ||
298 | struct clk *grf_clk; | ||
294 | struct clk *pllref_clk; | 299 | struct clk *pllref_clk; |
295 | struct clk *pclk; | 300 | struct clk *pclk; |
296 | struct clk *phy_cfg_clk; | 301 | struct clk *phy_cfg_clk; |
@@ -979,6 +984,17 @@ static void dw_mipi_dsi_encoder_enable(struct drm_encoder *encoder) | |||
979 | dw_mipi_dsi_dphy_interface_config(dsi); | 984 | dw_mipi_dsi_dphy_interface_config(dsi); |
980 | dw_mipi_dsi_clear_err(dsi); | 985 | dw_mipi_dsi_clear_err(dsi); |
981 | 986 | ||
987 | /* | ||
988 | * For the RK3399, the clk of grf must be enabled before writing grf | ||
989 | * register. And for RK3288 or other soc, this grf_clk must be NULL, | ||
990 | * the clk_prepare_enable return true directly. | ||
991 | */ | ||
992 | ret = clk_prepare_enable(dsi->grf_clk); | ||
993 | if (ret) { | ||
994 | dev_err(dsi->dev, "Failed to enable grf_clk: %d\n", ret); | ||
995 | return; | ||
996 | } | ||
997 | |||
982 | if (pdata->grf_dsi0_mode_reg) | 998 | if (pdata->grf_dsi0_mode_reg) |
983 | regmap_write(dsi->grf_regmap, pdata->grf_dsi0_mode_reg, | 999 | regmap_write(dsi->grf_regmap, pdata->grf_dsi0_mode_reg, |
984 | pdata->grf_dsi0_mode); | 1000 | pdata->grf_dsi0_mode); |
@@ -1003,6 +1019,8 @@ static void dw_mipi_dsi_encoder_enable(struct drm_encoder *encoder) | |||
1003 | regmap_write(dsi->grf_regmap, pdata->grf_switch_reg, val); | 1019 | regmap_write(dsi->grf_regmap, pdata->grf_switch_reg, val); |
1004 | dev_dbg(dsi->dev, "vop %s output to dsi0\n", (mux) ? "LIT" : "BIG"); | 1020 | dev_dbg(dsi->dev, "vop %s output to dsi0\n", (mux) ? "LIT" : "BIG"); |
1005 | dsi->dpms_mode = DRM_MODE_DPMS_ON; | 1021 | dsi->dpms_mode = DRM_MODE_DPMS_ON; |
1022 | |||
1023 | clk_disable_unprepare(dsi->grf_clk); | ||
1006 | } | 1024 | } |
1007 | 1025 | ||
1008 | static int | 1026 | static int |
@@ -1133,9 +1151,10 @@ static struct dw_mipi_dsi_plat_data rk3288_mipi_dsi_drv_data = { | |||
1133 | static struct dw_mipi_dsi_plat_data rk3399_mipi_dsi_drv_data = { | 1151 | static struct dw_mipi_dsi_plat_data rk3399_mipi_dsi_drv_data = { |
1134 | .dsi0_en_bit = RK3399_DSI0_SEL_VOP_LIT, | 1152 | .dsi0_en_bit = RK3399_DSI0_SEL_VOP_LIT, |
1135 | .dsi1_en_bit = RK3399_DSI1_SEL_VOP_LIT, | 1153 | .dsi1_en_bit = RK3399_DSI1_SEL_VOP_LIT, |
1136 | .grf_switch_reg = RK3399_GRF_SOC_CON19, | 1154 | .grf_switch_reg = RK3399_GRF_SOC_CON20, |
1137 | .grf_dsi0_mode = RK3399_GRF_DSI_MODE, | 1155 | .grf_dsi0_mode = RK3399_GRF_DSI_MODE, |
1138 | .grf_dsi0_mode_reg = RK3399_GRF_SOC_CON22, | 1156 | .grf_dsi0_mode_reg = RK3399_GRF_SOC_CON22, |
1157 | .flags = DW_MIPI_NEEDS_PHY_CFG_CLK | DW_MIPI_NEEDS_GRF_CLK, | ||
1139 | .max_data_lanes = 4, | 1158 | .max_data_lanes = 4, |
1140 | }; | 1159 | }; |
1141 | 1160 | ||
@@ -1227,15 +1246,22 @@ static int dw_mipi_dsi_bind(struct device *dev, struct device *master, | |||
1227 | clk_disable_unprepare(dsi->pclk); | 1246 | clk_disable_unprepare(dsi->pclk); |
1228 | } | 1247 | } |
1229 | 1248 | ||
1230 | dsi->phy_cfg_clk = devm_clk_get(dev, "phy_cfg"); | 1249 | if (pdata->flags & DW_MIPI_NEEDS_PHY_CFG_CLK) { |
1231 | if (IS_ERR(dsi->phy_cfg_clk)) { | 1250 | dsi->phy_cfg_clk = devm_clk_get(dev, "phy_cfg"); |
1232 | ret = PTR_ERR(dsi->phy_cfg_clk); | 1251 | if (IS_ERR(dsi->phy_cfg_clk)) { |
1233 | if (ret != -ENOENT) { | 1252 | ret = PTR_ERR(dsi->phy_cfg_clk); |
1234 | dev_err(dev, "Unable to get phy_cfg_clk: %d\n", ret); | 1253 | dev_err(dev, "Unable to get phy_cfg_clk: %d\n", ret); |
1235 | return ret; | 1254 | return ret; |
1236 | } | 1255 | } |
1237 | dsi->phy_cfg_clk = NULL; | 1256 | } |
1238 | dev_dbg(dev, "have not phy_cfg_clk\n"); | 1257 | |
1258 | if (pdata->flags & DW_MIPI_NEEDS_GRF_CLK) { | ||
1259 | dsi->grf_clk = devm_clk_get(dev, "grf"); | ||
1260 | if (IS_ERR(dsi->grf_clk)) { | ||
1261 | ret = PTR_ERR(dsi->grf_clk); | ||
1262 | dev_err(dev, "Unable to get grf_clk: %d\n", ret); | ||
1263 | return ret; | ||
1264 | } | ||
1239 | } | 1265 | } |
1240 | 1266 | ||
1241 | ret = clk_prepare_enable(dsi->pllref_clk); | 1267 | ret = clk_prepare_enable(dsi->pllref_clk); |
@@ -1304,7 +1330,7 @@ static int dw_mipi_dsi_remove(struct platform_device *pdev) | |||
1304 | return 0; | 1330 | return 0; |
1305 | } | 1331 | } |
1306 | 1332 | ||
1307 | static struct platform_driver dw_mipi_dsi_driver = { | 1333 | struct platform_driver dw_mipi_dsi_driver = { |
1308 | .probe = dw_mipi_dsi_probe, | 1334 | .probe = dw_mipi_dsi_probe, |
1309 | .remove = dw_mipi_dsi_remove, | 1335 | .remove = dw_mipi_dsi_remove, |
1310 | .driver = { | 1336 | .driver = { |
@@ -1312,9 +1338,3 @@ static struct platform_driver dw_mipi_dsi_driver = { | |||
1312 | .name = DRIVER_NAME, | 1338 | .name = DRIVER_NAME, |
1313 | }, | 1339 | }, |
1314 | }; | 1340 | }; |
1315 | module_platform_driver(dw_mipi_dsi_driver); | ||
1316 | |||
1317 | MODULE_DESCRIPTION("ROCKCHIP MIPI DSI host controller driver"); | ||
1318 | MODULE_AUTHOR("Chris Zhong <zyw@rock-chips.com>"); | ||
1319 | MODULE_LICENSE("GPL"); | ||
1320 | MODULE_ALIAS("platform:" DRIVER_NAME); | ||
diff --git a/drivers/gpu/drm/rockchip/dw_hdmi-rockchip.c b/drivers/gpu/drm/rockchip/dw_hdmi-rockchip.c index d53827413996..63dab6f1b191 100644 --- a/drivers/gpu/drm/rockchip/dw_hdmi-rockchip.c +++ b/drivers/gpu/drm/rockchip/dw_hdmi-rockchip.c | |||
@@ -325,7 +325,7 @@ static int dw_hdmi_rockchip_remove(struct platform_device *pdev) | |||
325 | return 0; | 325 | return 0; |
326 | } | 326 | } |
327 | 327 | ||
328 | static struct platform_driver dw_hdmi_rockchip_pltfm_driver = { | 328 | struct platform_driver dw_hdmi_rockchip_pltfm_driver = { |
329 | .probe = dw_hdmi_rockchip_probe, | 329 | .probe = dw_hdmi_rockchip_probe, |
330 | .remove = dw_hdmi_rockchip_remove, | 330 | .remove = dw_hdmi_rockchip_remove, |
331 | .driver = { | 331 | .driver = { |
@@ -333,11 +333,3 @@ static struct platform_driver dw_hdmi_rockchip_pltfm_driver = { | |||
333 | .of_match_table = dw_hdmi_rockchip_dt_ids, | 333 | .of_match_table = dw_hdmi_rockchip_dt_ids, |
334 | }, | 334 | }, |
335 | }; | 335 | }; |
336 | |||
337 | module_platform_driver(dw_hdmi_rockchip_pltfm_driver); | ||
338 | |||
339 | MODULE_AUTHOR("Andy Yan <andy.yan@rock-chips.com>"); | ||
340 | MODULE_AUTHOR("Yakir Yang <ykk@rock-chips.com>"); | ||
341 | MODULE_DESCRIPTION("Rockchip Specific DW-HDMI Driver Extension"); | ||
342 | MODULE_LICENSE("GPL"); | ||
343 | MODULE_ALIAS("platform:dwhdmi-rockchip"); | ||
diff --git a/drivers/gpu/drm/rockchip/inno_hdmi.c b/drivers/gpu/drm/rockchip/inno_hdmi.c index 006260de9dbd..7d9b75eb6c44 100644 --- a/drivers/gpu/drm/rockchip/inno_hdmi.c +++ b/drivers/gpu/drm/rockchip/inno_hdmi.c | |||
@@ -923,7 +923,7 @@ static const struct of_device_id inno_hdmi_dt_ids[] = { | |||
923 | }; | 923 | }; |
924 | MODULE_DEVICE_TABLE(of, inno_hdmi_dt_ids); | 924 | MODULE_DEVICE_TABLE(of, inno_hdmi_dt_ids); |
925 | 925 | ||
926 | static struct platform_driver inno_hdmi_driver = { | 926 | struct platform_driver inno_hdmi_driver = { |
927 | .probe = inno_hdmi_probe, | 927 | .probe = inno_hdmi_probe, |
928 | .remove = inno_hdmi_remove, | 928 | .remove = inno_hdmi_remove, |
929 | .driver = { | 929 | .driver = { |
@@ -931,11 +931,3 @@ static struct platform_driver inno_hdmi_driver = { | |||
931 | .of_match_table = inno_hdmi_dt_ids, | 931 | .of_match_table = inno_hdmi_dt_ids, |
932 | }, | 932 | }, |
933 | }; | 933 | }; |
934 | |||
935 | module_platform_driver(inno_hdmi_driver); | ||
936 | |||
937 | MODULE_AUTHOR("Zheng Yang <zhengyang@rock-chips.com>"); | ||
938 | MODULE_AUTHOR("Yakir Yang <ykk@rock-chips.com>"); | ||
939 | MODULE_DESCRIPTION("Rockchip Specific INNO-HDMI Driver"); | ||
940 | MODULE_LICENSE("GPL v2"); | ||
941 | MODULE_ALIAS("platform:innohdmi-rockchip"); | ||
diff --git a/drivers/gpu/drm/rockchip/rockchip_drm_drv.c b/drivers/gpu/drm/rockchip/rockchip_drm_drv.c index ccf456938792..cd7d02e1f758 100644 --- a/drivers/gpu/drm/rockchip/rockchip_drm_drv.c +++ b/drivers/gpu/drm/rockchip/rockchip_drm_drv.c | |||
@@ -304,34 +304,37 @@ static const struct dev_pm_ops rockchip_drm_pm_ops = { | |||
304 | rockchip_drm_sys_resume) | 304 | rockchip_drm_sys_resume) |
305 | }; | 305 | }; |
306 | 306 | ||
307 | static int compare_of(struct device *dev, void *data) | 307 | #define MAX_ROCKCHIP_SUB_DRIVERS 16 |
308 | { | 308 | static struct platform_driver *rockchip_sub_drivers[MAX_ROCKCHIP_SUB_DRIVERS]; |
309 | struct device_node *np = data; | 309 | static int num_rockchip_sub_drivers; |
310 | 310 | ||
311 | return dev->of_node == np; | 311 | static int compare_dev(struct device *dev, void *data) |
312 | { | ||
313 | return dev == (struct device *)data; | ||
312 | } | 314 | } |
313 | 315 | ||
314 | static void rockchip_add_endpoints(struct device *dev, | 316 | static struct component_match *rockchip_drm_match_add(struct device *dev) |
315 | struct component_match **match, | ||
316 | struct device_node *port) | ||
317 | { | 317 | { |
318 | struct device_node *ep, *remote; | 318 | struct component_match *match = NULL; |
319 | int i; | ||
319 | 320 | ||
320 | for_each_child_of_node(port, ep) { | 321 | for (i = 0; i < num_rockchip_sub_drivers; i++) { |
321 | remote = of_graph_get_remote_port_parent(ep); | 322 | struct platform_driver *drv = rockchip_sub_drivers[i]; |
322 | if (!remote || !of_device_is_available(remote)) { | 323 | struct device *p = NULL, *d; |
323 | of_node_put(remote); | 324 | |
324 | continue; | 325 | do { |
325 | } else if (!of_device_is_available(remote->parent)) { | 326 | d = bus_find_device(&platform_bus_type, p, &drv->driver, |
326 | dev_warn(dev, "parent device of %s is not available\n", | 327 | (void *)platform_bus_type.match); |
327 | remote->full_name); | 328 | put_device(p); |
328 | of_node_put(remote); | 329 | p = d; |
329 | continue; | ||
330 | } | ||
331 | 330 | ||
332 | drm_of_component_match_add(dev, match, compare_of, remote); | 331 | if (!d) |
333 | of_node_put(remote); | 332 | break; |
333 | component_match_add(dev, &match, compare_dev, d); | ||
334 | } while (true); | ||
334 | } | 335 | } |
336 | |||
337 | return match ?: ERR_PTR(-ENODEV); | ||
335 | } | 338 | } |
336 | 339 | ||
337 | static const struct component_master_ops rockchip_drm_ops = { | 340 | static const struct component_master_ops rockchip_drm_ops = { |
@@ -339,21 +342,16 @@ static const struct component_master_ops rockchip_drm_ops = { | |||
339 | .unbind = rockchip_drm_unbind, | 342 | .unbind = rockchip_drm_unbind, |
340 | }; | 343 | }; |
341 | 344 | ||
342 | static int rockchip_drm_platform_probe(struct platform_device *pdev) | 345 | static int rockchip_drm_platform_of_probe(struct device *dev) |
343 | { | 346 | { |
344 | struct device *dev = &pdev->dev; | ||
345 | struct component_match *match = NULL; | ||
346 | struct device_node *np = dev->of_node; | 347 | struct device_node *np = dev->of_node; |
347 | struct device_node *port; | 348 | struct device_node *port; |
349 | bool found = false; | ||
348 | int i; | 350 | int i; |
349 | 351 | ||
350 | if (!np) | 352 | if (!np) |
351 | return -ENODEV; | 353 | return -ENODEV; |
352 | /* | 354 | |
353 | * Bind the crtc ports first, so that | ||
354 | * drm_of_find_possible_crtcs called from encoder .bind callbacks | ||
355 | * works as expected. | ||
356 | */ | ||
357 | for (i = 0;; i++) { | 355 | for (i = 0;; i++) { |
358 | struct device_node *iommu; | 356 | struct device_node *iommu; |
359 | 357 | ||
@@ -377,9 +375,9 @@ static int rockchip_drm_platform_probe(struct platform_device *pdev) | |||
377 | is_support_iommu = false; | 375 | is_support_iommu = false; |
378 | } | 376 | } |
379 | 377 | ||
378 | found = true; | ||
379 | |||
380 | of_node_put(iommu); | 380 | of_node_put(iommu); |
381 | drm_of_component_match_add(dev, &match, compare_of, | ||
382 | port->parent); | ||
383 | of_node_put(port); | 381 | of_node_put(port); |
384 | } | 382 | } |
385 | 383 | ||
@@ -388,27 +386,27 @@ static int rockchip_drm_platform_probe(struct platform_device *pdev) | |||
388 | return -ENODEV; | 386 | return -ENODEV; |
389 | } | 387 | } |
390 | 388 | ||
391 | if (!match) { | 389 | if (!found) { |
392 | dev_err(dev, "No available vop found for display-subsystem.\n"); | 390 | dev_err(dev, "No available vop found for display-subsystem.\n"); |
393 | return -ENODEV; | 391 | return -ENODEV; |
394 | } | 392 | } |
395 | /* | ||
396 | * For each bound crtc, bind the encoders attached to its | ||
397 | * remote endpoint. | ||
398 | */ | ||
399 | for (i = 0;; i++) { | ||
400 | port = of_parse_phandle(np, "ports", i); | ||
401 | if (!port) | ||
402 | break; | ||
403 | 393 | ||
404 | if (!of_device_is_available(port->parent)) { | 394 | return 0; |
405 | of_node_put(port); | 395 | } |
406 | continue; | ||
407 | } | ||
408 | 396 | ||
409 | rockchip_add_endpoints(dev, &match, port); | 397 | static int rockchip_drm_platform_probe(struct platform_device *pdev) |
410 | of_node_put(port); | 398 | { |
411 | } | 399 | struct device *dev = &pdev->dev; |
400 | struct component_match *match = NULL; | ||
401 | int ret; | ||
402 | |||
403 | ret = rockchip_drm_platform_of_probe(dev); | ||
404 | if (ret) | ||
405 | return ret; | ||
406 | |||
407 | match = rockchip_drm_match_add(dev); | ||
408 | if (IS_ERR(match)) | ||
409 | return PTR_ERR(match); | ||
412 | 410 | ||
413 | return component_master_add_with_match(dev, &rockchip_drm_ops, match); | 411 | return component_master_add_with_match(dev, &rockchip_drm_ops, match); |
414 | } | 412 | } |
@@ -436,7 +434,54 @@ static struct platform_driver rockchip_drm_platform_driver = { | |||
436 | }, | 434 | }, |
437 | }; | 435 | }; |
438 | 436 | ||
439 | module_platform_driver(rockchip_drm_platform_driver); | 437 | #define ADD_ROCKCHIP_SUB_DRIVER(drv, cond) { \ |
438 | if (IS_ENABLED(cond) && \ | ||
439 | !WARN_ON(num_rockchip_sub_drivers >= MAX_ROCKCHIP_SUB_DRIVERS)) \ | ||
440 | rockchip_sub_drivers[num_rockchip_sub_drivers++] = &drv; \ | ||
441 | } | ||
442 | |||
443 | static int __init rockchip_drm_init(void) | ||
444 | { | ||
445 | int ret; | ||
446 | |||
447 | num_rockchip_sub_drivers = 0; | ||
448 | ADD_ROCKCHIP_SUB_DRIVER(vop_platform_driver, CONFIG_DRM_ROCKCHIP); | ||
449 | ADD_ROCKCHIP_SUB_DRIVER(rockchip_dp_driver, | ||
450 | CONFIG_ROCKCHIP_ANALOGIX_DP); | ||
451 | ADD_ROCKCHIP_SUB_DRIVER(cdn_dp_driver, CONFIG_ROCKCHIP_CDN_DP); | ||
452 | ADD_ROCKCHIP_SUB_DRIVER(dw_hdmi_rockchip_pltfm_driver, | ||
453 | CONFIG_ROCKCHIP_DW_HDMI); | ||
454 | ADD_ROCKCHIP_SUB_DRIVER(dw_mipi_dsi_driver, | ||
455 | CONFIG_ROCKCHIP_DW_MIPI_DSI); | ||
456 | ADD_ROCKCHIP_SUB_DRIVER(inno_hdmi_driver, CONFIG_ROCKCHIP_INNO_HDMI); | ||
457 | |||
458 | ret = platform_register_drivers(rockchip_sub_drivers, | ||
459 | num_rockchip_sub_drivers); | ||
460 | if (ret) | ||
461 | return ret; | ||
462 | |||
463 | ret = platform_driver_register(&rockchip_drm_platform_driver); | ||
464 | if (ret) | ||
465 | goto err_unreg_drivers; | ||
466 | |||
467 | return 0; | ||
468 | |||
469 | err_unreg_drivers: | ||
470 | platform_unregister_drivers(rockchip_sub_drivers, | ||
471 | num_rockchip_sub_drivers); | ||
472 | return ret; | ||
473 | } | ||
474 | |||
475 | static void __exit rockchip_drm_fini(void) | ||
476 | { | ||
477 | platform_driver_unregister(&rockchip_drm_platform_driver); | ||
478 | |||
479 | platform_unregister_drivers(rockchip_sub_drivers, | ||
480 | num_rockchip_sub_drivers); | ||
481 | } | ||
482 | |||
483 | module_init(rockchip_drm_init); | ||
484 | module_exit(rockchip_drm_fini); | ||
440 | 485 | ||
441 | MODULE_AUTHOR("Mark Yao <mark.yao@rock-chips.com>"); | 486 | MODULE_AUTHOR("Mark Yao <mark.yao@rock-chips.com>"); |
442 | MODULE_DESCRIPTION("ROCKCHIP DRM Driver"); | 487 | MODULE_DESCRIPTION("ROCKCHIP DRM Driver"); |
diff --git a/drivers/gpu/drm/rockchip/rockchip_drm_drv.h b/drivers/gpu/drm/rockchip/rockchip_drm_drv.h index 8aca219ec4c8..a48fcce3f5f6 100644 --- a/drivers/gpu/drm/rockchip/rockchip_drm_drv.h +++ b/drivers/gpu/drm/rockchip/rockchip_drm_drv.h | |||
@@ -65,4 +65,10 @@ void rockchip_drm_dma_detach_device(struct drm_device *drm_dev, | |||
65 | int rockchip_drm_wait_line_flag(struct drm_crtc *crtc, unsigned int line_num, | 65 | int rockchip_drm_wait_line_flag(struct drm_crtc *crtc, unsigned int line_num, |
66 | unsigned int mstimeout); | 66 | unsigned int mstimeout); |
67 | 67 | ||
68 | extern struct platform_driver cdn_dp_driver; | ||
69 | extern struct platform_driver dw_hdmi_rockchip_pltfm_driver; | ||
70 | extern struct platform_driver dw_mipi_dsi_driver; | ||
71 | extern struct platform_driver inno_hdmi_driver; | ||
72 | extern struct platform_driver rockchip_dp_driver; | ||
73 | extern struct platform_driver vop_platform_driver; | ||
68 | #endif /* _ROCKCHIP_DRM_DRV_H_ */ | 74 | #endif /* _ROCKCHIP_DRM_DRV_H_ */ |
diff --git a/drivers/gpu/drm/rockchip/rockchip_vop_reg.c b/drivers/gpu/drm/rockchip/rockchip_vop_reg.c index 91fbc7b52147..0da44442aab0 100644 --- a/drivers/gpu/drm/rockchip/rockchip_vop_reg.c +++ b/drivers/gpu/drm/rockchip/rockchip_vop_reg.c | |||
@@ -404,7 +404,7 @@ static int vop_remove(struct platform_device *pdev) | |||
404 | return 0; | 404 | return 0; |
405 | } | 405 | } |
406 | 406 | ||
407 | static struct platform_driver vop_platform_driver = { | 407 | struct platform_driver vop_platform_driver = { |
408 | .probe = vop_probe, | 408 | .probe = vop_probe, |
409 | .remove = vop_remove, | 409 | .remove = vop_remove, |
410 | .driver = { | 410 | .driver = { |
@@ -412,9 +412,3 @@ static struct platform_driver vop_platform_driver = { | |||
412 | .of_match_table = of_match_ptr(vop_driver_dt_match), | 412 | .of_match_table = of_match_ptr(vop_driver_dt_match), |
413 | }, | 413 | }, |
414 | }; | 414 | }; |
415 | |||
416 | module_platform_driver(vop_platform_driver); | ||
417 | |||
418 | MODULE_AUTHOR("Mark Yao <mark.yao@rock-chips.com>"); | ||
419 | MODULE_DESCRIPTION("ROCKCHIP VOP Driver"); | ||
420 | MODULE_LICENSE("GPL v2"); | ||
diff --git a/drivers/gpu/drm/shmobile/shmob_drm_crtc.c b/drivers/gpu/drm/shmobile/shmob_drm_crtc.c index 5fcabc04f307..e7738939a86d 100644 --- a/drivers/gpu/drm/shmobile/shmob_drm_crtc.c +++ b/drivers/gpu/drm/shmobile/shmob_drm_crtc.c | |||
@@ -449,7 +449,8 @@ void shmob_drm_crtc_finish_page_flip(struct shmob_drm_crtc *scrtc) | |||
449 | static int shmob_drm_crtc_page_flip(struct drm_crtc *crtc, | 449 | static int shmob_drm_crtc_page_flip(struct drm_crtc *crtc, |
450 | struct drm_framebuffer *fb, | 450 | struct drm_framebuffer *fb, |
451 | struct drm_pending_vblank_event *event, | 451 | struct drm_pending_vblank_event *event, |
452 | uint32_t page_flip_flags) | 452 | uint32_t page_flip_flags, |
453 | struct drm_modeset_acquire_ctx *ctx) | ||
453 | { | 454 | { |
454 | struct shmob_drm_crtc *scrtc = to_shmob_crtc(crtc); | 455 | struct shmob_drm_crtc *scrtc = to_shmob_crtc(crtc); |
455 | struct drm_device *dev = scrtc->crtc.dev; | 456 | struct drm_device *dev = scrtc->crtc.dev; |
diff --git a/drivers/gpu/drm/shmobile/shmob_drm_plane.c b/drivers/gpu/drm/shmobile/shmob_drm_plane.c index 2023a93cee2b..97f6e4a3eb0d 100644 --- a/drivers/gpu/drm/shmobile/shmob_drm_plane.c +++ b/drivers/gpu/drm/shmobile/shmob_drm_plane.c | |||
@@ -177,7 +177,8 @@ shmob_drm_plane_update(struct drm_plane *plane, struct drm_crtc *crtc, | |||
177 | struct drm_framebuffer *fb, int crtc_x, int crtc_y, | 177 | struct drm_framebuffer *fb, int crtc_x, int crtc_y, |
178 | unsigned int crtc_w, unsigned int crtc_h, | 178 | unsigned int crtc_w, unsigned int crtc_h, |
179 | uint32_t src_x, uint32_t src_y, | 179 | uint32_t src_x, uint32_t src_y, |
180 | uint32_t src_w, uint32_t src_h) | 180 | uint32_t src_w, uint32_t src_h, |
181 | struct drm_modeset_acquire_ctx *ctx) | ||
181 | { | 182 | { |
182 | struct shmob_drm_plane *splane = to_shmob_plane(plane); | 183 | struct shmob_drm_plane *splane = to_shmob_plane(plane); |
183 | struct shmob_drm_device *sdev = plane->dev->dev_private; | 184 | struct shmob_drm_device *sdev = plane->dev->dev_private; |
@@ -208,7 +209,8 @@ shmob_drm_plane_update(struct drm_plane *plane, struct drm_crtc *crtc, | |||
208 | return 0; | 209 | return 0; |
209 | } | 210 | } |
210 | 211 | ||
211 | static int shmob_drm_plane_disable(struct drm_plane *plane) | 212 | static int shmob_drm_plane_disable(struct drm_plane *plane, |
213 | struct drm_modeset_acquire_ctx *ctx) | ||
212 | { | 214 | { |
213 | struct shmob_drm_plane *splane = to_shmob_plane(plane); | 215 | struct shmob_drm_plane *splane = to_shmob_plane(plane); |
214 | struct shmob_drm_device *sdev = plane->dev->dev_private; | 216 | struct shmob_drm_device *sdev = plane->dev->dev_private; |
@@ -221,7 +223,7 @@ static int shmob_drm_plane_disable(struct drm_plane *plane) | |||
221 | 223 | ||
222 | static void shmob_drm_plane_destroy(struct drm_plane *plane) | 224 | static void shmob_drm_plane_destroy(struct drm_plane *plane) |
223 | { | 225 | { |
224 | shmob_drm_plane_disable(plane); | 226 | drm_plane_force_disable(plane); |
225 | drm_plane_cleanup(plane); | 227 | drm_plane_cleanup(plane); |
226 | } | 228 | } |
227 | 229 | ||
diff --git a/drivers/gpu/drm/tegra/dc.c b/drivers/gpu/drm/tegra/dc.c index 0db5d5a8d3b9..95b373f739f2 100644 --- a/drivers/gpu/drm/tegra/dc.c +++ b/drivers/gpu/drm/tegra/dc.c | |||
@@ -1382,7 +1382,7 @@ static int tegra_dc_show_regs(struct seq_file *s, void *data) | |||
1382 | struct tegra_dc *dc = node->info_ent->data; | 1382 | struct tegra_dc *dc = node->info_ent->data; |
1383 | int err = 0; | 1383 | int err = 0; |
1384 | 1384 | ||
1385 | drm_modeset_lock_crtc(&dc->base, NULL); | 1385 | drm_modeset_lock(&dc->base.mutex, NULL); |
1386 | 1386 | ||
1387 | if (!dc->base.state->active) { | 1387 | if (!dc->base.state->active) { |
1388 | err = -EBUSY; | 1388 | err = -EBUSY; |
@@ -1609,7 +1609,7 @@ static int tegra_dc_show_regs(struct seq_file *s, void *data) | |||
1609 | #undef DUMP_REG | 1609 | #undef DUMP_REG |
1610 | 1610 | ||
1611 | unlock: | 1611 | unlock: |
1612 | drm_modeset_unlock_crtc(&dc->base); | 1612 | drm_modeset_unlock(&dc->base.mutex); |
1613 | return err; | 1613 | return err; |
1614 | } | 1614 | } |
1615 | 1615 | ||
@@ -1620,7 +1620,7 @@ static int tegra_dc_show_crc(struct seq_file *s, void *data) | |||
1620 | int err = 0; | 1620 | int err = 0; |
1621 | u32 value; | 1621 | u32 value; |
1622 | 1622 | ||
1623 | drm_modeset_lock_crtc(&dc->base, NULL); | 1623 | drm_modeset_lock(&dc->base.mutex, NULL); |
1624 | 1624 | ||
1625 | if (!dc->base.state->active) { | 1625 | if (!dc->base.state->active) { |
1626 | err = -EBUSY; | 1626 | err = -EBUSY; |
@@ -1640,7 +1640,7 @@ static int tegra_dc_show_crc(struct seq_file *s, void *data) | |||
1640 | tegra_dc_writel(dc, 0, DC_COM_CRC_CONTROL); | 1640 | tegra_dc_writel(dc, 0, DC_COM_CRC_CONTROL); |
1641 | 1641 | ||
1642 | unlock: | 1642 | unlock: |
1643 | drm_modeset_unlock_crtc(&dc->base); | 1643 | drm_modeset_unlock(&dc->base.mutex); |
1644 | return err; | 1644 | return err; |
1645 | } | 1645 | } |
1646 | 1646 | ||
diff --git a/drivers/gpu/drm/tilcdc/tilcdc_crtc.c b/drivers/gpu/drm/tilcdc/tilcdc_crtc.c index c92faa8f7560..afd2a7b2aff7 100644 --- a/drivers/gpu/drm/tilcdc/tilcdc_crtc.c +++ b/drivers/gpu/drm/tilcdc/tilcdc_crtc.c | |||
@@ -579,7 +579,7 @@ static void tilcdc_crtc_recover_work(struct work_struct *work) | |||
579 | 579 | ||
580 | dev_info(crtc->dev->dev, "%s: Reset CRTC", __func__); | 580 | dev_info(crtc->dev->dev, "%s: Reset CRTC", __func__); |
581 | 581 | ||
582 | drm_modeset_lock_crtc(crtc, NULL); | 582 | drm_modeset_lock(&crtc->mutex, NULL); |
583 | 583 | ||
584 | if (!tilcdc_crtc_is_on(crtc)) | 584 | if (!tilcdc_crtc_is_on(crtc)) |
585 | goto out; | 585 | goto out; |
@@ -587,7 +587,7 @@ static void tilcdc_crtc_recover_work(struct work_struct *work) | |||
587 | tilcdc_crtc_disable(crtc); | 587 | tilcdc_crtc_disable(crtc); |
588 | tilcdc_crtc_enable(crtc); | 588 | tilcdc_crtc_enable(crtc); |
589 | out: | 589 | out: |
590 | drm_modeset_unlock_crtc(crtc); | 590 | drm_modeset_unlock(&crtc->mutex); |
591 | } | 591 | } |
592 | 592 | ||
593 | static void tilcdc_crtc_destroy(struct drm_crtc *crtc) | 593 | static void tilcdc_crtc_destroy(struct drm_crtc *crtc) |
@@ -595,9 +595,9 @@ static void tilcdc_crtc_destroy(struct drm_crtc *crtc) | |||
595 | struct tilcdc_crtc *tilcdc_crtc = to_tilcdc_crtc(crtc); | 595 | struct tilcdc_crtc *tilcdc_crtc = to_tilcdc_crtc(crtc); |
596 | struct tilcdc_drm_private *priv = crtc->dev->dev_private; | 596 | struct tilcdc_drm_private *priv = crtc->dev->dev_private; |
597 | 597 | ||
598 | drm_modeset_lock_crtc(crtc, NULL); | 598 | drm_modeset_lock(&crtc->mutex, NULL); |
599 | tilcdc_crtc_disable(crtc); | 599 | tilcdc_crtc_disable(crtc); |
600 | drm_modeset_unlock_crtc(crtc); | 600 | drm_modeset_unlock(&crtc->mutex); |
601 | 601 | ||
602 | flush_workqueue(priv->wq); | 602 | flush_workqueue(priv->wq); |
603 | 603 | ||
@@ -856,7 +856,7 @@ void tilcdc_crtc_update_clk(struct drm_crtc *crtc) | |||
856 | struct tilcdc_drm_private *priv = dev->dev_private; | 856 | struct tilcdc_drm_private *priv = dev->dev_private; |
857 | struct tilcdc_crtc *tilcdc_crtc = to_tilcdc_crtc(crtc); | 857 | struct tilcdc_crtc *tilcdc_crtc = to_tilcdc_crtc(crtc); |
858 | 858 | ||
859 | drm_modeset_lock_crtc(crtc, NULL); | 859 | drm_modeset_lock(&crtc->mutex, NULL); |
860 | if (tilcdc_crtc->lcd_fck_rate != clk_get_rate(priv->clk)) { | 860 | if (tilcdc_crtc->lcd_fck_rate != clk_get_rate(priv->clk)) { |
861 | if (tilcdc_crtc_is_on(crtc)) { | 861 | if (tilcdc_crtc_is_on(crtc)) { |
862 | pm_runtime_get_sync(dev->dev); | 862 | pm_runtime_get_sync(dev->dev); |
@@ -868,7 +868,7 @@ void tilcdc_crtc_update_clk(struct drm_crtc *crtc) | |||
868 | pm_runtime_put_sync(dev->dev); | 868 | pm_runtime_put_sync(dev->dev); |
869 | } | 869 | } |
870 | } | 870 | } |
871 | drm_modeset_unlock_crtc(crtc); | 871 | drm_modeset_unlock(&crtc->mutex); |
872 | } | 872 | } |
873 | 873 | ||
874 | #define SYNC_LOST_COUNT_LIMIT 50 | 874 | #define SYNC_LOST_COUNT_LIMIT 50 |
diff --git a/drivers/gpu/drm/tinydrm/core/tinydrm-core.c b/drivers/gpu/drm/tinydrm/core/tinydrm-core.c index 6a257dd08ee0..551709e6b114 100644 --- a/drivers/gpu/drm/tinydrm/core/tinydrm-core.c +++ b/drivers/gpu/drm/tinydrm/core/tinydrm-core.c | |||
@@ -122,21 +122,6 @@ void tinydrm_gem_cma_free_object(struct drm_gem_object *gem_obj) | |||
122 | } | 122 | } |
123 | EXPORT_SYMBOL_GPL(tinydrm_gem_cma_free_object); | 123 | EXPORT_SYMBOL_GPL(tinydrm_gem_cma_free_object); |
124 | 124 | ||
125 | const struct file_operations tinydrm_fops = { | ||
126 | .owner = THIS_MODULE, | ||
127 | .open = drm_open, | ||
128 | .release = drm_release, | ||
129 | .unlocked_ioctl = drm_ioctl, | ||
130 | #ifdef CONFIG_COMPAT | ||
131 | .compat_ioctl = drm_compat_ioctl, | ||
132 | #endif | ||
133 | .poll = drm_poll, | ||
134 | .read = drm_read, | ||
135 | .llseek = no_llseek, | ||
136 | .mmap = drm_gem_cma_mmap, | ||
137 | }; | ||
138 | EXPORT_SYMBOL(tinydrm_fops); | ||
139 | |||
140 | static struct drm_framebuffer * | 125 | static struct drm_framebuffer * |
141 | tinydrm_fb_create(struct drm_device *drm, struct drm_file *file_priv, | 126 | tinydrm_fb_create(struct drm_device *drm, struct drm_file *file_priv, |
142 | const struct drm_mode_fb_cmd2 *mode_cmd) | 127 | const struct drm_mode_fb_cmd2 *mode_cmd) |
@@ -251,7 +236,7 @@ static void tinydrm_unregister(struct tinydrm_device *tdev) | |||
251 | { | 236 | { |
252 | struct drm_fbdev_cma *fbdev_cma = tdev->fbdev_cma; | 237 | struct drm_fbdev_cma *fbdev_cma = tdev->fbdev_cma; |
253 | 238 | ||
254 | drm_crtc_force_disable_all(tdev->drm); | 239 | drm_atomic_helper_shutdown(tdev->drm); |
255 | /* don't restore fbdev in lastclose, keep pipeline disabled */ | 240 | /* don't restore fbdev in lastclose, keep pipeline disabled */ |
256 | tdev->fbdev_cma = NULL; | 241 | tdev->fbdev_cma = NULL; |
257 | drm_dev_unregister(tdev->drm); | 242 | drm_dev_unregister(tdev->drm); |
@@ -302,7 +287,7 @@ EXPORT_SYMBOL(devm_tinydrm_register); | |||
302 | */ | 287 | */ |
303 | void tinydrm_shutdown(struct tinydrm_device *tdev) | 288 | void tinydrm_shutdown(struct tinydrm_device *tdev) |
304 | { | 289 | { |
305 | drm_crtc_force_disable_all(tdev->drm); | 290 | drm_atomic_helper_shutdown(tdev->drm); |
306 | } | 291 | } |
307 | EXPORT_SYMBOL(tinydrm_shutdown); | 292 | EXPORT_SYMBOL(tinydrm_shutdown); |
308 | 293 | ||
diff --git a/drivers/gpu/drm/tinydrm/mi0283qt.c b/drivers/gpu/drm/tinydrm/mi0283qt.c index b29fe86158f7..482ff1c3db61 100644 --- a/drivers/gpu/drm/tinydrm/mi0283qt.c +++ b/drivers/gpu/drm/tinydrm/mi0283qt.c | |||
@@ -132,9 +132,12 @@ static const struct drm_display_mode mi0283qt_mode = { | |||
132 | TINYDRM_MODE(320, 240, 58, 43), | 132 | TINYDRM_MODE(320, 240, 58, 43), |
133 | }; | 133 | }; |
134 | 134 | ||
135 | DEFINE_DRM_GEM_CMA_FOPS(mi0283qt_fops); | ||
136 | |||
135 | static struct drm_driver mi0283qt_driver = { | 137 | static struct drm_driver mi0283qt_driver = { |
136 | .driver_features = DRIVER_GEM | DRIVER_MODESET | DRIVER_PRIME | | 138 | .driver_features = DRIVER_GEM | DRIVER_MODESET | DRIVER_PRIME | |
137 | DRIVER_ATOMIC, | 139 | DRIVER_ATOMIC, |
140 | .fops = &mi0283qt_fops, | ||
138 | TINYDRM_GEM_DRIVER_OPS, | 141 | TINYDRM_GEM_DRIVER_OPS, |
139 | .lastclose = tinydrm_lastclose, | 142 | .lastclose = tinydrm_lastclose, |
140 | .debugfs_init = mipi_dbi_debugfs_init, | 143 | .debugfs_init = mipi_dbi_debugfs_init, |
diff --git a/drivers/gpu/drm/udl/udl_modeset.c b/drivers/gpu/drm/udl/udl_modeset.c index f2b2481cad52..5bcae7649795 100644 --- a/drivers/gpu/drm/udl/udl_modeset.c +++ b/drivers/gpu/drm/udl/udl_modeset.c | |||
@@ -361,7 +361,8 @@ static void udl_crtc_destroy(struct drm_crtc *crtc) | |||
361 | static int udl_crtc_page_flip(struct drm_crtc *crtc, | 361 | static int udl_crtc_page_flip(struct drm_crtc *crtc, |
362 | struct drm_framebuffer *fb, | 362 | struct drm_framebuffer *fb, |
363 | struct drm_pending_vblank_event *event, | 363 | struct drm_pending_vblank_event *event, |
364 | uint32_t page_flip_flags) | 364 | uint32_t page_flip_flags, |
365 | struct drm_modeset_acquire_ctx *ctx) | ||
365 | { | 366 | { |
366 | struct udl_framebuffer *ufb = to_udl_fb(fb); | 367 | struct udl_framebuffer *ufb = to_udl_fb(fb); |
367 | struct drm_device *dev = crtc->dev; | 368 | struct drm_device *dev = crtc->dev; |
diff --git a/drivers/gpu/drm/vc4/vc4_crtc.c b/drivers/gpu/drm/vc4/vc4_crtc.c index 24edd0c22cc9..865e9f494bcc 100644 --- a/drivers/gpu/drm/vc4/vc4_crtc.c +++ b/drivers/gpu/drm/vc4/vc4_crtc.c | |||
@@ -807,12 +807,13 @@ static int vc4_async_page_flip(struct drm_crtc *crtc, | |||
807 | static int vc4_page_flip(struct drm_crtc *crtc, | 807 | static int vc4_page_flip(struct drm_crtc *crtc, |
808 | struct drm_framebuffer *fb, | 808 | struct drm_framebuffer *fb, |
809 | struct drm_pending_vblank_event *event, | 809 | struct drm_pending_vblank_event *event, |
810 | uint32_t flags) | 810 | uint32_t flags, |
811 | struct drm_modeset_acquire_ctx *ctx) | ||
811 | { | 812 | { |
812 | if (flags & DRM_MODE_PAGE_FLIP_ASYNC) | 813 | if (flags & DRM_MODE_PAGE_FLIP_ASYNC) |
813 | return vc4_async_page_flip(crtc, fb, event, flags); | 814 | return vc4_async_page_flip(crtc, fb, event, flags); |
814 | else | 815 | else |
815 | return drm_atomic_helper_page_flip(crtc, fb, event, flags); | 816 | return drm_atomic_helper_page_flip(crtc, fb, event, flags, ctx); |
816 | } | 817 | } |
817 | 818 | ||
818 | static struct drm_crtc_state *vc4_crtc_duplicate_state(struct drm_crtc *crtc) | 819 | static struct drm_crtc_state *vc4_crtc_duplicate_state(struct drm_crtc *crtc) |
diff --git a/drivers/gpu/drm/vc4/vc4_plane.c b/drivers/gpu/drm/vc4/vc4_plane.c index 0f4564beb017..d34cd5393a9b 100644 --- a/drivers/gpu/drm/vc4/vc4_plane.c +++ b/drivers/gpu/drm/vc4/vc4_plane.c | |||
@@ -756,7 +756,8 @@ vc4_update_plane(struct drm_plane *plane, | |||
756 | int crtc_x, int crtc_y, | 756 | int crtc_x, int crtc_y, |
757 | unsigned int crtc_w, unsigned int crtc_h, | 757 | unsigned int crtc_w, unsigned int crtc_h, |
758 | uint32_t src_x, uint32_t src_y, | 758 | uint32_t src_x, uint32_t src_y, |
759 | uint32_t src_w, uint32_t src_h) | 759 | uint32_t src_w, uint32_t src_h, |
760 | struct drm_modeset_acquire_ctx *ctx) | ||
760 | { | 761 | { |
761 | struct drm_plane_state *plane_state; | 762 | struct drm_plane_state *plane_state; |
762 | struct vc4_plane_state *vc4_state; | 763 | struct vc4_plane_state *vc4_state; |
@@ -817,7 +818,8 @@ out: | |||
817 | crtc_x, crtc_y, | 818 | crtc_x, crtc_y, |
818 | crtc_w, crtc_h, | 819 | crtc_w, crtc_h, |
819 | src_x, src_y, | 820 | src_x, src_y, |
820 | src_w, src_h); | 821 | src_w, src_h, |
822 | ctx); | ||
821 | } | 823 | } |
822 | 824 | ||
823 | static const struct drm_plane_funcs vc4_plane_funcs = { | 825 | static const struct drm_plane_funcs vc4_plane_funcs = { |
diff --git a/drivers/gpu/drm/vmwgfx/vmwgfx_kms.c b/drivers/gpu/drm/vmwgfx/vmwgfx_kms.c index c18c81f63ac3..6078654d033b 100644 --- a/drivers/gpu/drm/vmwgfx/vmwgfx_kms.c +++ b/drivers/gpu/drm/vmwgfx/vmwgfx_kms.c | |||
@@ -2947,10 +2947,11 @@ vmw_kms_create_implicit_placement_property(struct vmw_private *dev_priv, | |||
2947 | * the vmwgfx modesetting. So explicitly clear that member before calling | 2947 | * the vmwgfx modesetting. So explicitly clear that member before calling |
2948 | * into drm_atomic_helper_set_config. | 2948 | * into drm_atomic_helper_set_config. |
2949 | */ | 2949 | */ |
2950 | int vmw_kms_set_config(struct drm_mode_set *set) | 2950 | int vmw_kms_set_config(struct drm_mode_set *set, |
2951 | struct drm_modeset_acquire_ctx *ctx) | ||
2951 | { | 2952 | { |
2952 | if (set && set->mode) | 2953 | if (set && set->mode) |
2953 | set->mode->type = 0; | 2954 | set->mode->type = 0; |
2954 | 2955 | ||
2955 | return drm_atomic_helper_set_config(set); | 2956 | return drm_atomic_helper_set_config(set, ctx); |
2956 | } | 2957 | } |
diff --git a/drivers/gpu/drm/vmwgfx/vmwgfx_kms.h b/drivers/gpu/drm/vmwgfx/vmwgfx_kms.h index 9c161d29aaeb..0c226b2adea5 100644 --- a/drivers/gpu/drm/vmwgfx/vmwgfx_kms.h +++ b/drivers/gpu/drm/vmwgfx/vmwgfx_kms.h | |||
@@ -453,6 +453,7 @@ int vmw_kms_stdu_dma(struct vmw_private *dev_priv, | |||
453 | bool to_surface, | 453 | bool to_surface, |
454 | bool interruptible); | 454 | bool interruptible); |
455 | 455 | ||
456 | int vmw_kms_set_config(struct drm_mode_set *set); | 456 | int vmw_kms_set_config(struct drm_mode_set *set, |
457 | struct drm_modeset_acquire_ctx *ctx); | ||
457 | 458 | ||
458 | #endif | 459 | #endif |
diff --git a/drivers/gpu/drm/vmwgfx/vmwgfx_scrn.c b/drivers/gpu/drm/vmwgfx/vmwgfx_scrn.c index 2664e4c16750..8d7dc9def7c2 100644 --- a/drivers/gpu/drm/vmwgfx/vmwgfx_scrn.c +++ b/drivers/gpu/drm/vmwgfx/vmwgfx_scrn.c | |||
@@ -310,7 +310,8 @@ static void vmw_sou_crtc_helper_disable(struct drm_crtc *crtc) | |||
310 | static int vmw_sou_crtc_page_flip(struct drm_crtc *crtc, | 310 | static int vmw_sou_crtc_page_flip(struct drm_crtc *crtc, |
311 | struct drm_framebuffer *new_fb, | 311 | struct drm_framebuffer *new_fb, |
312 | struct drm_pending_vblank_event *event, | 312 | struct drm_pending_vblank_event *event, |
313 | uint32_t flags) | 313 | uint32_t flags, |
314 | struct drm_modeset_acquire_ctx *ctx) | ||
314 | { | 315 | { |
315 | struct vmw_private *dev_priv = vmw_priv(crtc->dev); | 316 | struct vmw_private *dev_priv = vmw_priv(crtc->dev); |
316 | struct drm_framebuffer *old_fb = crtc->primary->fb; | 317 | struct drm_framebuffer *old_fb = crtc->primary->fb; |
@@ -323,7 +324,7 @@ static int vmw_sou_crtc_page_flip(struct drm_crtc *crtc, | |||
323 | return -EINVAL; | 324 | return -EINVAL; |
324 | 325 | ||
325 | flags &= ~DRM_MODE_PAGE_FLIP_ASYNC; | 326 | flags &= ~DRM_MODE_PAGE_FLIP_ASYNC; |
326 | ret = drm_atomic_helper_page_flip(crtc, new_fb, NULL, flags); | 327 | ret = drm_atomic_helper_page_flip(crtc, new_fb, NULL, flags, ctx); |
327 | if (ret) { | 328 | if (ret) { |
328 | DRM_ERROR("Page flip error %d.\n", ret); | 329 | DRM_ERROR("Page flip error %d.\n", ret); |
329 | return ret; | 330 | return ret; |
diff --git a/drivers/gpu/drm/vmwgfx/vmwgfx_stdu.c b/drivers/gpu/drm/vmwgfx/vmwgfx_stdu.c index e872ffe5f0db..bad31bdf09b6 100644 --- a/drivers/gpu/drm/vmwgfx/vmwgfx_stdu.c +++ b/drivers/gpu/drm/vmwgfx/vmwgfx_stdu.c | |||
@@ -481,7 +481,8 @@ static void vmw_stdu_crtc_helper_disable(struct drm_crtc *crtc) | |||
481 | static int vmw_stdu_crtc_page_flip(struct drm_crtc *crtc, | 481 | static int vmw_stdu_crtc_page_flip(struct drm_crtc *crtc, |
482 | struct drm_framebuffer *new_fb, | 482 | struct drm_framebuffer *new_fb, |
483 | struct drm_pending_vblank_event *event, | 483 | struct drm_pending_vblank_event *event, |
484 | uint32_t flags) | 484 | uint32_t flags, |
485 | struct drm_modeset_acquire_ctx *ctx) | ||
485 | 486 | ||
486 | { | 487 | { |
487 | struct vmw_private *dev_priv = vmw_priv(crtc->dev); | 488 | struct vmw_private *dev_priv = vmw_priv(crtc->dev); |
@@ -504,7 +505,7 @@ static int vmw_stdu_crtc_page_flip(struct drm_crtc *crtc, | |||
504 | * don't hand it to the helper. | 505 | * don't hand it to the helper. |
505 | */ | 506 | */ |
506 | flags &= ~DRM_MODE_PAGE_FLIP_ASYNC; | 507 | flags &= ~DRM_MODE_PAGE_FLIP_ASYNC; |
507 | ret = drm_atomic_helper_page_flip(crtc, new_fb, NULL, flags); | 508 | ret = drm_atomic_helper_page_flip(crtc, new_fb, NULL, flags, ctx); |
508 | if (ret) { | 509 | if (ret) { |
509 | DRM_ERROR("Page flip error %d.\n", ret); | 510 | DRM_ERROR("Page flip error %d.\n", ret); |
510 | return ret; | 511 | return ret; |
diff --git a/drivers/gpu/drm/zte/zx_hdmi.c b/drivers/gpu/drm/zte/zx_hdmi.c index c47b9cbfe270..0df7366e594b 100644 --- a/drivers/gpu/drm/zte/zx_hdmi.c +++ b/drivers/gpu/drm/zte/zx_hdmi.c | |||
@@ -50,7 +50,6 @@ struct zx_hdmi { | |||
50 | struct clk *xclk; | 50 | struct clk *xclk; |
51 | bool sink_is_hdmi; | 51 | bool sink_is_hdmi; |
52 | bool sink_has_audio; | 52 | bool sink_has_audio; |
53 | const struct vou_inf *inf; | ||
54 | struct platform_device *audio_pdev; | 53 | struct platform_device *audio_pdev; |
55 | }; | 54 | }; |
56 | 55 | ||
diff --git a/drivers/pci/pci.h b/drivers/pci/pci.h index 8dd38e69d6f2..4dbf9f96ae5b 100644 --- a/drivers/pci/pci.h +++ b/drivers/pci/pci.h | |||
@@ -3,6 +3,8 @@ | |||
3 | 3 | ||
4 | #define PCI_FIND_CAP_TTL 48 | 4 | #define PCI_FIND_CAP_TTL 48 |
5 | 5 | ||
6 | #define PCI_VSEC_ID_INTEL_TBT 0x1234 /* Thunderbolt */ | ||
7 | |||
6 | extern const unsigned char pcie_link_speed[]; | 8 | extern const unsigned char pcie_link_speed[]; |
7 | 9 | ||
8 | bool pcie_cap_has_lnkctl(const struct pci_dev *dev); | 10 | bool pcie_cap_has_lnkctl(const struct pci_dev *dev); |
diff --git a/drivers/pci/probe.c b/drivers/pci/probe.c index dfc9a2794141..90592d424e9b 100644 --- a/drivers/pci/probe.c +++ b/drivers/pci/probe.c | |||
@@ -1208,6 +1208,24 @@ void set_pcie_hotplug_bridge(struct pci_dev *pdev) | |||
1208 | pdev->is_hotplug_bridge = 1; | 1208 | pdev->is_hotplug_bridge = 1; |
1209 | } | 1209 | } |
1210 | 1210 | ||
1211 | static void set_pcie_thunderbolt(struct pci_dev *dev) | ||
1212 | { | ||
1213 | int vsec = 0; | ||
1214 | u32 header; | ||
1215 | |||
1216 | while ((vsec = pci_find_next_ext_capability(dev, vsec, | ||
1217 | PCI_EXT_CAP_ID_VNDR))) { | ||
1218 | pci_read_config_dword(dev, vsec + PCI_VNDR_HEADER, &header); | ||
1219 | |||
1220 | /* Is the device part of a Thunderbolt controller? */ | ||
1221 | if (dev->vendor == PCI_VENDOR_ID_INTEL && | ||
1222 | PCI_VNDR_HEADER_ID(header) == PCI_VSEC_ID_INTEL_TBT) { | ||
1223 | dev->is_thunderbolt = 1; | ||
1224 | return; | ||
1225 | } | ||
1226 | } | ||
1227 | } | ||
1228 | |||
1211 | /** | 1229 | /** |
1212 | * pci_ext_cfg_is_aliased - is ext config space just an alias of std config? | 1230 | * pci_ext_cfg_is_aliased - is ext config space just an alias of std config? |
1213 | * @dev: PCI device | 1231 | * @dev: PCI device |
@@ -1360,6 +1378,9 @@ int pci_setup_device(struct pci_dev *dev) | |||
1360 | /* need to have dev->class ready */ | 1378 | /* need to have dev->class ready */ |
1361 | dev->cfg_size = pci_cfg_space_size(dev); | 1379 | dev->cfg_size = pci_cfg_space_size(dev); |
1362 | 1380 | ||
1381 | /* need to have dev->cfg_size ready */ | ||
1382 | set_pcie_thunderbolt(dev); | ||
1383 | |||
1363 | /* "Unknown power state" */ | 1384 | /* "Unknown power state" */ |
1364 | dev->current_state = PCI_UNKNOWN; | 1385 | dev->current_state = PCI_UNKNOWN; |
1365 | 1386 | ||
diff --git a/drivers/platform/x86/apple-gmux.c b/drivers/platform/x86/apple-gmux.c index a66be137324c..623d322447a2 100644 --- a/drivers/platform/x86/apple-gmux.c +++ b/drivers/platform/x86/apple-gmux.c | |||
@@ -60,6 +60,7 @@ struct apple_gmux_data { | |||
60 | /* switcheroo data */ | 60 | /* switcheroo data */ |
61 | acpi_handle dhandle; | 61 | acpi_handle dhandle; |
62 | int gpe; | 62 | int gpe; |
63 | bool external_switchable; | ||
63 | enum vga_switcheroo_client_id switch_state_display; | 64 | enum vga_switcheroo_client_id switch_state_display; |
64 | enum vga_switcheroo_client_id switch_state_ddc; | 65 | enum vga_switcheroo_client_id switch_state_ddc; |
65 | enum vga_switcheroo_client_id switch_state_external; | 66 | enum vga_switcheroo_client_id switch_state_external; |
@@ -358,6 +359,19 @@ static const struct backlight_ops gmux_bl_ops = { | |||
358 | * ports while the discrete GPU is asleep, but currently we do not make use | 359 | * ports while the discrete GPU is asleep, but currently we do not make use |
359 | * of this feature. | 360 | * of this feature. |
360 | * | 361 | * |
362 | * Our switching policy for the external port is that on those generations | ||
363 | * which are able to switch it fully, the port is switched together with the | ||
364 | * panel when IGD / DIS commands are issued to vga_switcheroo. It is thus | ||
365 | * possible to drive e.g. a beamer on battery power with the integrated GPU. | ||
366 | * The user may manually switch to the discrete GPU if more performance is | ||
367 | * needed. | ||
368 | * | ||
369 | * On all newer generations, the external port can only be driven by the | ||
370 | * discrete GPU. If a display is plugged in while the panel is switched to | ||
371 | * the integrated GPU, *both* GPUs will be in use for maximum performance. | ||
372 | * To decrease power consumption, the user may manually switch to the | ||
373 | * discrete GPU, thereby suspending the integrated GPU. | ||
374 | * | ||
361 | * gmux' initial switch state on bootup is user configurable via the EFI | 375 | * gmux' initial switch state on bootup is user configurable via the EFI |
362 | * variable ``gpu-power-prefs-fa4ce28d-b62f-4c99-9cc3-6815686e30f9`` (5th byte, | 376 | * variable ``gpu-power-prefs-fa4ce28d-b62f-4c99-9cc3-6815686e30f9`` (5th byte, |
363 | * 1 = IGD, 0 = DIS). Based on this setting, the EFI firmware tells gmux to | 377 | * 1 = IGD, 0 = DIS). Based on this setting, the EFI firmware tells gmux to |
@@ -414,7 +428,8 @@ static int gmux_switchto(enum vga_switcheroo_client_id id) | |||
414 | { | 428 | { |
415 | apple_gmux_data->switch_state_ddc = id; | 429 | apple_gmux_data->switch_state_ddc = id; |
416 | apple_gmux_data->switch_state_display = id; | 430 | apple_gmux_data->switch_state_display = id; |
417 | apple_gmux_data->switch_state_external = id; | 431 | if (apple_gmux_data->external_switchable) |
432 | apple_gmux_data->switch_state_external = id; | ||
418 | 433 | ||
419 | gmux_write_switch_state(apple_gmux_data); | 434 | gmux_write_switch_state(apple_gmux_data); |
420 | 435 | ||
@@ -601,6 +616,11 @@ static struct pci_dev *gmux_get_io_pdev(void) | |||
601 | return NULL; | 616 | return NULL; |
602 | } | 617 | } |
603 | 618 | ||
619 | static int is_thunderbolt(struct device *dev, void *data) | ||
620 | { | ||
621 | return to_pci_dev(dev)->is_thunderbolt; | ||
622 | } | ||
623 | |||
604 | static int gmux_probe(struct pnp_dev *pnp, const struct pnp_device_id *id) | 624 | static int gmux_probe(struct pnp_dev *pnp, const struct pnp_device_id *id) |
605 | { | 625 | { |
606 | struct apple_gmux_data *gmux_data; | 626 | struct apple_gmux_data *gmux_data; |
@@ -755,6 +775,15 @@ static int gmux_probe(struct pnp_dev *pnp, const struct pnp_device_id *id) | |||
755 | gmux_data->gpe = -1; | 775 | gmux_data->gpe = -1; |
756 | } | 776 | } |
757 | 777 | ||
778 | /* | ||
779 | * If Thunderbolt is present, the external DP port is not fully | ||
780 | * switchable. Force its AUX channel to the discrete GPU. | ||
781 | */ | ||
782 | gmux_data->external_switchable = | ||
783 | !bus_for_each_dev(&pci_bus_type, NULL, NULL, is_thunderbolt); | ||
784 | if (!gmux_data->external_switchable) | ||
785 | gmux_write8(gmux_data, GMUX_PORT_SWITCH_EXTERNAL, 3); | ||
786 | |||
758 | apple_gmux_data = gmux_data; | 787 | apple_gmux_data = gmux_data; |
759 | init_completion(&gmux_data->powerchange_done); | 788 | init_completion(&gmux_data->powerchange_done); |
760 | gmux_enable_interrupts(gmux_data); | 789 | gmux_enable_interrupts(gmux_data); |
diff --git a/include/drm/drmP.h b/include/drm/drmP.h index 0e383438f793..3bfafcdb8710 100644 --- a/include/drm/drmP.h +++ b/include/drm/drmP.h | |||
@@ -78,6 +78,8 @@ | |||
78 | #include <drm/drm_prime.h> | 78 | #include <drm/drm_prime.h> |
79 | #include <drm/drm_pci.h> | 79 | #include <drm/drm_pci.h> |
80 | #include <drm/drm_file.h> | 80 | #include <drm/drm_file.h> |
81 | #include <drm/drm_debugfs.h> | ||
82 | #include <drm/drm_ioctl.h> | ||
81 | 83 | ||
82 | struct module; | 84 | struct module; |
83 | 85 | ||
@@ -316,54 +318,10 @@ struct pci_controller; | |||
316 | 318 | ||
317 | #define DRM_IF_VERSION(maj, min) (maj << 16 | min) | 319 | #define DRM_IF_VERSION(maj, min) (maj << 16 | min) |
318 | 320 | ||
319 | /** | ||
320 | * Ioctl function type. | ||
321 | * | ||
322 | * \param inode device inode. | ||
323 | * \param file_priv DRM file private pointer. | ||
324 | * \param cmd command. | ||
325 | * \param arg argument. | ||
326 | */ | ||
327 | typedef int drm_ioctl_t(struct drm_device *dev, void *data, | ||
328 | struct drm_file *file_priv); | ||
329 | |||
330 | typedef int drm_ioctl_compat_t(struct file *filp, unsigned int cmd, | ||
331 | unsigned long arg); | ||
332 | |||
333 | #define DRM_IOCTL_NR(n) _IOC_NR(n) | ||
334 | #define DRM_MAJOR 226 | ||
335 | |||
336 | #define DRM_AUTH 0x1 | ||
337 | #define DRM_MASTER 0x2 | ||
338 | #define DRM_ROOT_ONLY 0x4 | ||
339 | #define DRM_CONTROL_ALLOW 0x8 | ||
340 | #define DRM_UNLOCKED 0x10 | ||
341 | #define DRM_RENDER_ALLOW 0x20 | ||
342 | |||
343 | struct drm_ioctl_desc { | ||
344 | unsigned int cmd; | ||
345 | int flags; | ||
346 | drm_ioctl_t *func; | ||
347 | const char *name; | ||
348 | }; | ||
349 | |||
350 | /** | ||
351 | * Creates a driver or general drm_ioctl_desc array entry for the given | ||
352 | * ioctl, for use by drm_ioctl(). | ||
353 | */ | ||
354 | |||
355 | #define DRM_IOCTL_DEF_DRV(ioctl, _func, _flags) \ | ||
356 | [DRM_IOCTL_NR(DRM_IOCTL_##ioctl) - DRM_COMMAND_BASE] = { \ | ||
357 | .cmd = DRM_IOCTL_##ioctl, \ | ||
358 | .func = _func, \ | ||
359 | .flags = _flags, \ | ||
360 | .name = #ioctl \ | ||
361 | } | ||
362 | 321 | ||
363 | /* Flags and return codes for get_vblank_timestamp() driver function. */ | 322 | /* Flags and return codes for get_vblank_timestamp() driver function. */ |
364 | #define DRM_CALLED_FROM_VBLIRQ 1 | 323 | #define DRM_CALLED_FROM_VBLIRQ 1 |
365 | #define DRM_VBLANKTIME_SCANOUTPOS_METHOD (1 << 0) | 324 | #define DRM_VBLANKTIME_SCANOUTPOS_METHOD (1 << 0) |
366 | #define DRM_VBLANKTIME_IN_VBLANK (1 << 1) | ||
367 | 325 | ||
368 | /* get_scanout_position() return flags */ | 326 | /* get_scanout_position() return flags */ |
369 | #define DRM_SCANOUTPOS_VALID (1 << 0) | 327 | #define DRM_SCANOUTPOS_VALID (1 << 0) |
@@ -371,27 +329,6 @@ struct drm_ioctl_desc { | |||
371 | #define DRM_SCANOUTPOS_ACCURATE (1 << 2) | 329 | #define DRM_SCANOUTPOS_ACCURATE (1 << 2) |
372 | 330 | ||
373 | /** | 331 | /** |
374 | * Info file list entry. This structure represents a debugfs or proc file to | ||
375 | * be created by the drm core | ||
376 | */ | ||
377 | struct drm_info_list { | ||
378 | const char *name; /** file name */ | ||
379 | int (*show)(struct seq_file*, void*); /** show callback */ | ||
380 | u32 driver_features; /**< Required driver features for this entry */ | ||
381 | void *data; | ||
382 | }; | ||
383 | |||
384 | /** | ||
385 | * debugfs node structure. This structure represents a debugfs file. | ||
386 | */ | ||
387 | struct drm_info_node { | ||
388 | struct list_head list; | ||
389 | struct drm_minor *minor; | ||
390 | const struct drm_info_list *info_ent; | ||
391 | struct dentry *dent; | ||
392 | }; | ||
393 | |||
394 | /** | ||
395 | * DRM device structure. This structure represent a complete card that | 332 | * DRM device structure. This structure represent a complete card that |
396 | * may contain multiple heads. | 333 | * may contain multiple heads. |
397 | */ | 334 | */ |
@@ -569,51 +506,12 @@ static inline int drm_device_is_unplugged(struct drm_device *dev) | |||
569 | /*@{*/ | 506 | /*@{*/ |
570 | 507 | ||
571 | /* Driver support (drm_drv.h) */ | 508 | /* Driver support (drm_drv.h) */ |
572 | extern int drm_ioctl_permit(u32 flags, struct drm_file *file_priv); | ||
573 | extern long drm_ioctl(struct file *filp, | ||
574 | unsigned int cmd, unsigned long arg); | ||
575 | #ifdef CONFIG_COMPAT | ||
576 | extern long drm_compat_ioctl(struct file *filp, | ||
577 | unsigned int cmd, unsigned long arg); | ||
578 | #else | ||
579 | /* Let drm_compat_ioctl be assigned to .compat_ioctl unconditionally */ | ||
580 | #define drm_compat_ioctl NULL | ||
581 | #endif | ||
582 | extern bool drm_ioctl_flags(unsigned int nr, unsigned int *flags); | ||
583 | |||
584 | /* Misc. IOCTL support (drm_ioctl.c) */ | ||
585 | int drm_noop(struct drm_device *dev, void *data, | ||
586 | struct drm_file *file_priv); | ||
587 | int drm_invalid_op(struct drm_device *dev, void *data, | ||
588 | struct drm_file *file_priv); | ||
589 | 509 | ||
590 | /* | 510 | /* |
591 | * These are exported to drivers so that they can implement fencing using | 511 | * These are exported to drivers so that they can implement fencing using |
592 | * DMA quiscent + idle. DMA quiescent usually requires the hardware lock. | 512 | * DMA quiscent + idle. DMA quiescent usually requires the hardware lock. |
593 | */ | 513 | */ |
594 | 514 | ||
595 | /* Debugfs support */ | ||
596 | #if defined(CONFIG_DEBUG_FS) | ||
597 | extern int drm_debugfs_create_files(const struct drm_info_list *files, | ||
598 | int count, struct dentry *root, | ||
599 | struct drm_minor *minor); | ||
600 | extern int drm_debugfs_remove_files(const struct drm_info_list *files, | ||
601 | int count, struct drm_minor *minor); | ||
602 | #else | ||
603 | static inline int drm_debugfs_create_files(const struct drm_info_list *files, | ||
604 | int count, struct dentry *root, | ||
605 | struct drm_minor *minor) | ||
606 | { | ||
607 | return 0; | ||
608 | } | ||
609 | |||
610 | static inline int drm_debugfs_remove_files(const struct drm_info_list *files, | ||
611 | int count, struct drm_minor *minor) | ||
612 | { | ||
613 | return 0; | ||
614 | } | ||
615 | #endif | ||
616 | |||
617 | /* sysfs support (drm_sysfs.c) */ | 515 | /* sysfs support (drm_sysfs.c) */ |
618 | extern void drm_sysfs_hotplug_event(struct drm_device *dev); | 516 | extern void drm_sysfs_hotplug_event(struct drm_device *dev); |
619 | 517 | ||
diff --git a/include/drm/drm_atomic.h b/include/drm/drm_atomic.h index 0147a047878d..fd33ed5eaeb4 100644 --- a/include/drm/drm_atomic.h +++ b/include/drm/drm_atomic.h | |||
@@ -498,6 +498,23 @@ int __must_check drm_atomic_nonblocking_commit(struct drm_atomic_state *state); | |||
498 | 498 | ||
499 | void drm_state_dump(struct drm_device *dev, struct drm_printer *p); | 499 | void drm_state_dump(struct drm_device *dev, struct drm_printer *p); |
500 | 500 | ||
501 | /** | ||
502 | * for_each_connector_in_state - iterate over all connectors in an atomic update | ||
503 | * @__state: &struct drm_atomic_state pointer | ||
504 | * @connector: &struct drm_connector iteration cursor | ||
505 | * @connector_state: &struct drm_connector_state iteration cursor | ||
506 | * @__i: int iteration cursor, for macro-internal use | ||
507 | * | ||
508 | * This iterates over all connectors in an atomic update. Note that before the | ||
509 | * software state is committed (by calling drm_atomic_helper_swap_state(), this | ||
510 | * points to the new state, while afterwards it points to the old state. Due to | ||
511 | * this tricky confusion this macro is deprecated. | ||
512 | * | ||
513 | * FIXME: | ||
514 | * | ||
515 | * Replace all usage of this with one of the explicit iterators below and then | ||
516 | * remove this macro. | ||
517 | */ | ||
501 | #define for_each_connector_in_state(__state, connector, connector_state, __i) \ | 518 | #define for_each_connector_in_state(__state, connector, connector_state, __i) \ |
502 | for ((__i) = 0; \ | 519 | for ((__i) = 0; \ |
503 | (__i) < (__state)->num_connector && \ | 520 | (__i) < (__state)->num_connector && \ |
@@ -506,6 +523,20 @@ void drm_state_dump(struct drm_device *dev, struct drm_printer *p); | |||
506 | (__i)++) \ | 523 | (__i)++) \ |
507 | for_each_if (connector) | 524 | for_each_if (connector) |
508 | 525 | ||
526 | /** | ||
527 | * for_each_oldnew_connector_in_state - iterate over all connectors in an atomic update | ||
528 | * @__state: &struct drm_atomic_state pointer | ||
529 | * @connector: &struct drm_connector iteration cursor | ||
530 | * @old_connector_state: &struct drm_connector_state iteration cursor for the | ||
531 | * old state | ||
532 | * @new_connector_state: &struct drm_connector_state iteration cursor for the | ||
533 | * new state | ||
534 | * @__i: int iteration cursor, for macro-internal use | ||
535 | * | ||
536 | * This iterates over all connectors in an atomic update, tracking both old and | ||
537 | * new state. This is useful in places where the state delta needs to be | ||
538 | * considered, for example in atomic check functions. | ||
539 | */ | ||
509 | #define for_each_oldnew_connector_in_state(__state, connector, old_connector_state, new_connector_state, __i) \ | 540 | #define for_each_oldnew_connector_in_state(__state, connector, old_connector_state, new_connector_state, __i) \ |
510 | for ((__i) = 0; \ | 541 | for ((__i) = 0; \ |
511 | (__i) < (__state)->num_connector && \ | 542 | (__i) < (__state)->num_connector && \ |
@@ -515,6 +546,18 @@ void drm_state_dump(struct drm_device *dev, struct drm_printer *p); | |||
515 | (__i)++) \ | 546 | (__i)++) \ |
516 | for_each_if (connector) | 547 | for_each_if (connector) |
517 | 548 | ||
549 | /** | ||
550 | * for_each_old_connector_in_state - iterate over all connectors in an atomic update | ||
551 | * @__state: &struct drm_atomic_state pointer | ||
552 | * @connector: &struct drm_connector iteration cursor | ||
553 | * @old_connector_state: &struct drm_connector_state iteration cursor for the | ||
554 | * old state | ||
555 | * @__i: int iteration cursor, for macro-internal use | ||
556 | * | ||
557 | * This iterates over all connectors in an atomic update, tracking only the old | ||
558 | * state. This is useful in disable functions, where we need the old state the | ||
559 | * hardware is still in. | ||
560 | */ | ||
518 | #define for_each_old_connector_in_state(__state, connector, old_connector_state, __i) \ | 561 | #define for_each_old_connector_in_state(__state, connector, old_connector_state, __i) \ |
519 | for ((__i) = 0; \ | 562 | for ((__i) = 0; \ |
520 | (__i) < (__state)->num_connector && \ | 563 | (__i) < (__state)->num_connector && \ |
@@ -523,6 +566,18 @@ void drm_state_dump(struct drm_device *dev, struct drm_printer *p); | |||
523 | (__i)++) \ | 566 | (__i)++) \ |
524 | for_each_if (connector) | 567 | for_each_if (connector) |
525 | 568 | ||
569 | /** | ||
570 | * for_each_new_connector_in_state - iterate over all connectors in an atomic update | ||
571 | * @__state: &struct drm_atomic_state pointer | ||
572 | * @connector: &struct drm_connector iteration cursor | ||
573 | * @new_connector_state: &struct drm_connector_state iteration cursor for the | ||
574 | * new state | ||
575 | * @__i: int iteration cursor, for macro-internal use | ||
576 | * | ||
577 | * This iterates over all connectors in an atomic update, tracking only the new | ||
578 | * state. This is useful in enable functions, where we need the new state the | ||
579 | * hardware should be in when the atomic commit operation has completed. | ||
580 | */ | ||
526 | #define for_each_new_connector_in_state(__state, connector, new_connector_state, __i) \ | 581 | #define for_each_new_connector_in_state(__state, connector, new_connector_state, __i) \ |
527 | for ((__i) = 0; \ | 582 | for ((__i) = 0; \ |
528 | (__i) < (__state)->num_connector && \ | 583 | (__i) < (__state)->num_connector && \ |
@@ -531,6 +586,23 @@ void drm_state_dump(struct drm_device *dev, struct drm_printer *p); | |||
531 | (__i)++) \ | 586 | (__i)++) \ |
532 | for_each_if (connector) | 587 | for_each_if (connector) |
533 | 588 | ||
589 | /** | ||
590 | * for_each_crtc_in_state - iterate over all connectors in an atomic update | ||
591 | * @__state: &struct drm_atomic_state pointer | ||
592 | * @crtc: &struct drm_crtc iteration cursor | ||
593 | * @crtc_state: &struct drm_crtc_state iteration cursor | ||
594 | * @__i: int iteration cursor, for macro-internal use | ||
595 | * | ||
596 | * This iterates over all CRTCs in an atomic update. Note that before the | ||
597 | * software state is committed (by calling drm_atomic_helper_swap_state(), this | ||
598 | * points to the new state, while afterwards it points to the old state. Due to | ||
599 | * this tricky confusion this macro is deprecated. | ||
600 | * | ||
601 | * FIXME: | ||
602 | * | ||
603 | * Replace all usage of this with one of the explicit iterators below and then | ||
604 | * remove this macro. | ||
605 | */ | ||
534 | #define for_each_crtc_in_state(__state, crtc, crtc_state, __i) \ | 606 | #define for_each_crtc_in_state(__state, crtc, crtc_state, __i) \ |
535 | for ((__i) = 0; \ | 607 | for ((__i) = 0; \ |
536 | (__i) < (__state)->dev->mode_config.num_crtc && \ | 608 | (__i) < (__state)->dev->mode_config.num_crtc && \ |
@@ -539,6 +611,18 @@ void drm_state_dump(struct drm_device *dev, struct drm_printer *p); | |||
539 | (__i)++) \ | 611 | (__i)++) \ |
540 | for_each_if (crtc_state) | 612 | for_each_if (crtc_state) |
541 | 613 | ||
614 | /** | ||
615 | * for_each_oldnew_crtc_in_state - iterate over all CRTCs in an atomic update | ||
616 | * @__state: &struct drm_atomic_state pointer | ||
617 | * @crtc: &struct drm_crtc iteration cursor | ||
618 | * @old_crtc_state: &struct drm_crtc_state iteration cursor for the old state | ||
619 | * @new_crtc_state: &struct drm_crtc_state iteration cursor for the new state | ||
620 | * @__i: int iteration cursor, for macro-internal use | ||
621 | * | ||
622 | * This iterates over all CRTCs in an atomic update, tracking both old and | ||
623 | * new state. This is useful in places where the state delta needs to be | ||
624 | * considered, for example in atomic check functions. | ||
625 | */ | ||
542 | #define for_each_oldnew_crtc_in_state(__state, crtc, old_crtc_state, new_crtc_state, __i) \ | 626 | #define for_each_oldnew_crtc_in_state(__state, crtc, old_crtc_state, new_crtc_state, __i) \ |
543 | for ((__i) = 0; \ | 627 | for ((__i) = 0; \ |
544 | (__i) < (__state)->dev->mode_config.num_crtc && \ | 628 | (__i) < (__state)->dev->mode_config.num_crtc && \ |
@@ -548,6 +632,17 @@ void drm_state_dump(struct drm_device *dev, struct drm_printer *p); | |||
548 | (__i)++) \ | 632 | (__i)++) \ |
549 | for_each_if (crtc) | 633 | for_each_if (crtc) |
550 | 634 | ||
635 | /** | ||
636 | * for_each_old_crtc_in_state - iterate over all CRTCs in an atomic update | ||
637 | * @__state: &struct drm_atomic_state pointer | ||
638 | * @crtc: &struct drm_crtc iteration cursor | ||
639 | * @old_crtc_state: &struct drm_crtc_state iteration cursor for the old state | ||
640 | * @__i: int iteration cursor, for macro-internal use | ||
641 | * | ||
642 | * This iterates over all CRTCs in an atomic update, tracking only the old | ||
643 | * state. This is useful in disable functions, where we need the old state the | ||
644 | * hardware is still in. | ||
645 | */ | ||
551 | #define for_each_old_crtc_in_state(__state, crtc, old_crtc_state, __i) \ | 646 | #define for_each_old_crtc_in_state(__state, crtc, old_crtc_state, __i) \ |
552 | for ((__i) = 0; \ | 647 | for ((__i) = 0; \ |
553 | (__i) < (__state)->dev->mode_config.num_crtc && \ | 648 | (__i) < (__state)->dev->mode_config.num_crtc && \ |
@@ -556,6 +651,17 @@ void drm_state_dump(struct drm_device *dev, struct drm_printer *p); | |||
556 | (__i)++) \ | 651 | (__i)++) \ |
557 | for_each_if (crtc) | 652 | for_each_if (crtc) |
558 | 653 | ||
654 | /** | ||
655 | * for_each_new_crtc_in_state - iterate over all CRTCs in an atomic update | ||
656 | * @__state: &struct drm_atomic_state pointer | ||
657 | * @crtc: &struct drm_crtc iteration cursor | ||
658 | * @new_crtc_state: &struct drm_crtc_state iteration cursor for the new state | ||
659 | * @__i: int iteration cursor, for macro-internal use | ||
660 | * | ||
661 | * This iterates over all CRTCs in an atomic update, tracking only the new | ||
662 | * state. This is useful in enable functions, where we need the new state the | ||
663 | * hardware should be in when the atomic commit operation has completed. | ||
664 | */ | ||
559 | #define for_each_new_crtc_in_state(__state, crtc, new_crtc_state, __i) \ | 665 | #define for_each_new_crtc_in_state(__state, crtc, new_crtc_state, __i) \ |
560 | for ((__i) = 0; \ | 666 | for ((__i) = 0; \ |
561 | (__i) < (__state)->dev->mode_config.num_crtc && \ | 667 | (__i) < (__state)->dev->mode_config.num_crtc && \ |
@@ -564,6 +670,23 @@ void drm_state_dump(struct drm_device *dev, struct drm_printer *p); | |||
564 | (__i)++) \ | 670 | (__i)++) \ |
565 | for_each_if (crtc) | 671 | for_each_if (crtc) |
566 | 672 | ||
673 | /** | ||
674 | * for_each_plane_in_state - iterate over all planes in an atomic update | ||
675 | * @__state: &struct drm_atomic_state pointer | ||
676 | * @plane: &struct drm_plane iteration cursor | ||
677 | * @plane_state: &struct drm_plane_state iteration cursor | ||
678 | * @__i: int iteration cursor, for macro-internal use | ||
679 | * | ||
680 | * This iterates over all planes in an atomic update. Note that before the | ||
681 | * software state is committed (by calling drm_atomic_helper_swap_state(), this | ||
682 | * points to the new state, while afterwards it points to the old state. Due to | ||
683 | * this tricky confusion this macro is deprecated. | ||
684 | * | ||
685 | * FIXME: | ||
686 | * | ||
687 | * Replace all usage of this with one of the explicit iterators below and then | ||
688 | * remove this macro. | ||
689 | */ | ||
567 | #define for_each_plane_in_state(__state, plane, plane_state, __i) \ | 690 | #define for_each_plane_in_state(__state, plane, plane_state, __i) \ |
568 | for ((__i) = 0; \ | 691 | for ((__i) = 0; \ |
569 | (__i) < (__state)->dev->mode_config.num_total_plane && \ | 692 | (__i) < (__state)->dev->mode_config.num_total_plane && \ |
@@ -572,6 +695,18 @@ void drm_state_dump(struct drm_device *dev, struct drm_printer *p); | |||
572 | (__i)++) \ | 695 | (__i)++) \ |
573 | for_each_if (plane_state) | 696 | for_each_if (plane_state) |
574 | 697 | ||
698 | /** | ||
699 | * for_each_oldnew_plane_in_state - iterate over all planes in an atomic update | ||
700 | * @__state: &struct drm_atomic_state pointer | ||
701 | * @plane: &struct drm_plane iteration cursor | ||
702 | * @old_plane_state: &struct drm_plane_state iteration cursor for the old state | ||
703 | * @new_plane_state: &struct drm_plane_state iteration cursor for the new state | ||
704 | * @__i: int iteration cursor, for macro-internal use | ||
705 | * | ||
706 | * This iterates over all planes in an atomic update, tracking both old and | ||
707 | * new state. This is useful in places where the state delta needs to be | ||
708 | * considered, for example in atomic check functions. | ||
709 | */ | ||
575 | #define for_each_oldnew_plane_in_state(__state, plane, old_plane_state, new_plane_state, __i) \ | 710 | #define for_each_oldnew_plane_in_state(__state, plane, old_plane_state, new_plane_state, __i) \ |
576 | for ((__i) = 0; \ | 711 | for ((__i) = 0; \ |
577 | (__i) < (__state)->dev->mode_config.num_total_plane && \ | 712 | (__i) < (__state)->dev->mode_config.num_total_plane && \ |
@@ -581,6 +716,17 @@ void drm_state_dump(struct drm_device *dev, struct drm_printer *p); | |||
581 | (__i)++) \ | 716 | (__i)++) \ |
582 | for_each_if (plane) | 717 | for_each_if (plane) |
583 | 718 | ||
719 | /** | ||
720 | * for_each_old_plane_in_state - iterate over all planes in an atomic update | ||
721 | * @__state: &struct drm_atomic_state pointer | ||
722 | * @plane: &struct drm_plane iteration cursor | ||
723 | * @old_plane_state: &struct drm_plane_state iteration cursor for the old state | ||
724 | * @__i: int iteration cursor, for macro-internal use | ||
725 | * | ||
726 | * This iterates over all planes in an atomic update, tracking only the old | ||
727 | * state. This is useful in disable functions, where we need the old state the | ||
728 | * hardware is still in. | ||
729 | */ | ||
584 | #define for_each_old_plane_in_state(__state, plane, old_plane_state, __i) \ | 730 | #define for_each_old_plane_in_state(__state, plane, old_plane_state, __i) \ |
585 | for ((__i) = 0; \ | 731 | for ((__i) = 0; \ |
586 | (__i) < (__state)->dev->mode_config.num_total_plane && \ | 732 | (__i) < (__state)->dev->mode_config.num_total_plane && \ |
@@ -589,6 +735,17 @@ void drm_state_dump(struct drm_device *dev, struct drm_printer *p); | |||
589 | (__i)++) \ | 735 | (__i)++) \ |
590 | for_each_if (plane) | 736 | for_each_if (plane) |
591 | 737 | ||
738 | /** | ||
739 | * for_each_new_plane_in_state - iterate over all planes in an atomic update | ||
740 | * @__state: &struct drm_atomic_state pointer | ||
741 | * @plane: &struct drm_plane iteration cursor | ||
742 | * @new_plane_state: &struct drm_plane_state iteration cursor for the new state | ||
743 | * @__i: int iteration cursor, for macro-internal use | ||
744 | * | ||
745 | * This iterates over all planes in an atomic update, tracking only the new | ||
746 | * state. This is useful in enable functions, where we need the new state the | ||
747 | * hardware should be in when the atomic commit operation has completed. | ||
748 | */ | ||
592 | #define for_each_new_plane_in_state(__state, plane, new_plane_state, __i) \ | 749 | #define for_each_new_plane_in_state(__state, plane, new_plane_state, __i) \ |
593 | for ((__i) = 0; \ | 750 | for ((__i) = 0; \ |
594 | (__i) < (__state)->dev->mode_config.num_total_plane && \ | 751 | (__i) < (__state)->dev->mode_config.num_total_plane && \ |
@@ -603,7 +760,7 @@ void drm_state_dump(struct drm_device *dev, struct drm_printer *p); | |||
603 | * | 760 | * |
604 | * To give drivers flexibility &struct drm_crtc_state has 3 booleans to track | 761 | * To give drivers flexibility &struct drm_crtc_state has 3 booleans to track |
605 | * whether the state CRTC changed enough to need a full modeset cycle: | 762 | * whether the state CRTC changed enough to need a full modeset cycle: |
606 | * connectors_changed, mode_changed and active_changed. This helper simply | 763 | * planes_changed, mode_changed and active_changed. This helper simply |
607 | * combines these three to compute the overall need for a modeset for @state. | 764 | * combines these three to compute the overall need for a modeset for @state. |
608 | * | 765 | * |
609 | * The atomic helper code sets these booleans, but drivers can and should | 766 | * The atomic helper code sets these booleans, but drivers can and should |
diff --git a/include/drm/drm_atomic_helper.h b/include/drm/drm_atomic_helper.h index dc16274987c7..fd395dc050ee 100644 --- a/include/drm/drm_atomic_helper.h +++ b/include/drm/drm_atomic_helper.h | |||
@@ -94,16 +94,20 @@ int drm_atomic_helper_update_plane(struct drm_plane *plane, | |||
94 | int crtc_x, int crtc_y, | 94 | int crtc_x, int crtc_y, |
95 | unsigned int crtc_w, unsigned int crtc_h, | 95 | unsigned int crtc_w, unsigned int crtc_h, |
96 | uint32_t src_x, uint32_t src_y, | 96 | uint32_t src_x, uint32_t src_y, |
97 | uint32_t src_w, uint32_t src_h); | 97 | uint32_t src_w, uint32_t src_h, |
98 | int drm_atomic_helper_disable_plane(struct drm_plane *plane); | 98 | struct drm_modeset_acquire_ctx *ctx); |
99 | int drm_atomic_helper_disable_plane(struct drm_plane *plane, | ||
100 | struct drm_modeset_acquire_ctx *ctx); | ||
99 | int __drm_atomic_helper_disable_plane(struct drm_plane *plane, | 101 | int __drm_atomic_helper_disable_plane(struct drm_plane *plane, |
100 | struct drm_plane_state *plane_state); | 102 | struct drm_plane_state *plane_state); |
101 | int drm_atomic_helper_set_config(struct drm_mode_set *set); | 103 | int drm_atomic_helper_set_config(struct drm_mode_set *set, |
104 | struct drm_modeset_acquire_ctx *ctx); | ||
102 | int __drm_atomic_helper_set_config(struct drm_mode_set *set, | 105 | int __drm_atomic_helper_set_config(struct drm_mode_set *set, |
103 | struct drm_atomic_state *state); | 106 | struct drm_atomic_state *state); |
104 | 107 | ||
105 | int drm_atomic_helper_disable_all(struct drm_device *dev, | 108 | int drm_atomic_helper_disable_all(struct drm_device *dev, |
106 | struct drm_modeset_acquire_ctx *ctx); | 109 | struct drm_modeset_acquire_ctx *ctx); |
110 | void drm_atomic_helper_shutdown(struct drm_device *dev); | ||
107 | struct drm_atomic_state *drm_atomic_helper_suspend(struct drm_device *dev); | 111 | struct drm_atomic_state *drm_atomic_helper_suspend(struct drm_device *dev); |
108 | int drm_atomic_helper_commit_duplicated_state(struct drm_atomic_state *state, | 112 | int drm_atomic_helper_commit_duplicated_state(struct drm_atomic_state *state, |
109 | struct drm_modeset_acquire_ctx *ctx); | 113 | struct drm_modeset_acquire_ctx *ctx); |
@@ -122,13 +126,15 @@ int drm_atomic_helper_connector_set_property(struct drm_connector *connector, | |||
122 | int drm_atomic_helper_page_flip(struct drm_crtc *crtc, | 126 | int drm_atomic_helper_page_flip(struct drm_crtc *crtc, |
123 | struct drm_framebuffer *fb, | 127 | struct drm_framebuffer *fb, |
124 | struct drm_pending_vblank_event *event, | 128 | struct drm_pending_vblank_event *event, |
125 | uint32_t flags); | 129 | uint32_t flags, |
130 | struct drm_modeset_acquire_ctx *ctx); | ||
126 | int drm_atomic_helper_page_flip_target( | 131 | int drm_atomic_helper_page_flip_target( |
127 | struct drm_crtc *crtc, | 132 | struct drm_crtc *crtc, |
128 | struct drm_framebuffer *fb, | 133 | struct drm_framebuffer *fb, |
129 | struct drm_pending_vblank_event *event, | 134 | struct drm_pending_vblank_event *event, |
130 | uint32_t flags, | 135 | uint32_t flags, |
131 | uint32_t target); | 136 | uint32_t target, |
137 | struct drm_modeset_acquire_ctx *ctx); | ||
132 | int drm_atomic_helper_connector_dpms(struct drm_connector *connector, | 138 | int drm_atomic_helper_connector_dpms(struct drm_connector *connector, |
133 | int mode); | 139 | int mode); |
134 | struct drm_encoder * | 140 | struct drm_encoder * |
diff --git a/include/drm/drm_connector.h b/include/drm/drm_connector.h index f8b766d70a46..941f57f311aa 100644 --- a/include/drm/drm_connector.h +++ b/include/drm/drm_connector.h | |||
@@ -133,6 +133,7 @@ struct drm_scdc { | |||
133 | * This information is available in CEA-861-F extension blocks (like HF-VSDB). | 133 | * This information is available in CEA-861-F extension blocks (like HF-VSDB). |
134 | */ | 134 | */ |
135 | struct drm_hdmi_info { | 135 | struct drm_hdmi_info { |
136 | /** @scdc: sink's scdc support and capabilities */ | ||
136 | struct drm_scdc scdc; | 137 | struct drm_scdc scdc; |
137 | }; | 138 | }; |
138 | 139 | ||
@@ -655,7 +656,6 @@ struct drm_cmdline_mode { | |||
655 | * @bad_edid_counter: track sinks that give us an EDID with invalid checksum | 656 | * @bad_edid_counter: track sinks that give us an EDID with invalid checksum |
656 | * @edid_corrupt: indicates whether the last read EDID was corrupt | 657 | * @edid_corrupt: indicates whether the last read EDID was corrupt |
657 | * @debugfs_entry: debugfs directory for this connector | 658 | * @debugfs_entry: debugfs directory for this connector |
658 | * @state: current atomic state for this connector | ||
659 | * @has_tile: is this connector connected to a tiled monitor | 659 | * @has_tile: is this connector connected to a tiled monitor |
660 | * @tile_group: tile group for the connected monitor | 660 | * @tile_group: tile group for the connected monitor |
661 | * @tile_is_single_monitor: whether the tile is one monitor housing | 661 | * @tile_is_single_monitor: whether the tile is one monitor housing |
@@ -823,6 +823,21 @@ struct drm_connector { | |||
823 | 823 | ||
824 | struct dentry *debugfs_entry; | 824 | struct dentry *debugfs_entry; |
825 | 825 | ||
826 | /** | ||
827 | * @state: | ||
828 | * | ||
829 | * Current atomic state for this connector. | ||
830 | * | ||
831 | * This is protected by @drm_mode_config.connection_mutex. Note that | ||
832 | * nonblocking atomic commits access the current connector state without | ||
833 | * taking locks. Either by going through the &struct drm_atomic_state | ||
834 | * pointers, see for_each_connector_in_state(), | ||
835 | * for_each_oldnew_connector_in_state(), | ||
836 | * for_each_old_connector_in_state() and | ||
837 | * for_each_new_connector_in_state(). Or through careful ordering of | ||
838 | * atomic commit operations as implemented in the atomic helpers, see | ||
839 | * &struct drm_crtc_commit. | ||
840 | */ | ||
826 | struct drm_connector_state *state; | 841 | struct drm_connector_state *state; |
827 | 842 | ||
828 | /* DisplayID bits */ | 843 | /* DisplayID bits */ |
diff --git a/include/drm/drm_crtc.h b/include/drm/drm_crtc.h index 6ef59da3fd8e..2be2192b1373 100644 --- a/include/drm/drm_crtc.h +++ b/include/drm/drm_crtc.h | |||
@@ -347,7 +347,8 @@ struct drm_crtc_funcs { | |||
347 | * | 347 | * |
348 | * 0 on success or a negative error code on failure. | 348 | * 0 on success or a negative error code on failure. |
349 | */ | 349 | */ |
350 | int (*set_config)(struct drm_mode_set *set); | 350 | int (*set_config)(struct drm_mode_set *set, |
351 | struct drm_modeset_acquire_ctx *ctx); | ||
351 | 352 | ||
352 | /** | 353 | /** |
353 | * @page_flip: | 354 | * @page_flip: |
@@ -405,7 +406,8 @@ struct drm_crtc_funcs { | |||
405 | int (*page_flip)(struct drm_crtc *crtc, | 406 | int (*page_flip)(struct drm_crtc *crtc, |
406 | struct drm_framebuffer *fb, | 407 | struct drm_framebuffer *fb, |
407 | struct drm_pending_vblank_event *event, | 408 | struct drm_pending_vblank_event *event, |
408 | uint32_t flags); | 409 | uint32_t flags, |
410 | struct drm_modeset_acquire_ctx *ctx); | ||
409 | 411 | ||
410 | /** | 412 | /** |
411 | * @page_flip_target: | 413 | * @page_flip_target: |
@@ -423,7 +425,8 @@ struct drm_crtc_funcs { | |||
423 | int (*page_flip_target)(struct drm_crtc *crtc, | 425 | int (*page_flip_target)(struct drm_crtc *crtc, |
424 | struct drm_framebuffer *fb, | 426 | struct drm_framebuffer *fb, |
425 | struct drm_pending_vblank_event *event, | 427 | struct drm_pending_vblank_event *event, |
426 | uint32_t flags, uint32_t target); | 428 | uint32_t flags, uint32_t target, |
429 | struct drm_modeset_acquire_ctx *ctx); | ||
427 | 430 | ||
428 | /** | 431 | /** |
429 | * @set_property: | 432 | * @set_property: |
@@ -590,9 +593,12 @@ struct drm_crtc_funcs { | |||
590 | * When CRC generation is enabled, the driver should call | 593 | * When CRC generation is enabled, the driver should call |
591 | * drm_crtc_add_crc_entry() at each frame, providing any information | 594 | * drm_crtc_add_crc_entry() at each frame, providing any information |
592 | * that characterizes the frame contents in the crcN arguments, as | 595 | * that characterizes the frame contents in the crcN arguments, as |
593 | * provided from the configured source. Drivers must accept a "auto" | 596 | * provided from the configured source. Drivers must accept an "auto" |
594 | * source name that will select a default source for this CRTC. | 597 | * source name that will select a default source for this CRTC. |
595 | * | 598 | * |
599 | * Note that "auto" can depend upon the current modeset configuration, | ||
600 | * e.g. it could pick an encoder or output specific CRC sampling point. | ||
601 | * | ||
596 | * This callback is optional if the driver does not support any CRC | 602 | * This callback is optional if the driver does not support any CRC |
597 | * generation functionality. | 603 | * generation functionality. |
598 | * | 604 | * |
@@ -696,10 +702,12 @@ struct drm_crtc { | |||
696 | /** | 702 | /** |
697 | * @mutex: | 703 | * @mutex: |
698 | * | 704 | * |
699 | * This provides a read lock for the overall crtc state (mode, dpms | 705 | * This provides a read lock for the overall CRTC state (mode, dpms |
700 | * state, ...) and a write lock for everything which can be update | 706 | * state, ...) and a write lock for everything which can be update |
701 | * without a full modeset (fb, cursor data, crtc properties ...). A full | 707 | * without a full modeset (fb, cursor data, CRTC properties ...). A full |
702 | * modeset also need to grab &drm_mode_config.connection_mutex. | 708 | * modeset also need to grab &drm_mode_config.connection_mutex. |
709 | * | ||
710 | * For atomic drivers specifically this protects @state. | ||
703 | */ | 711 | */ |
704 | struct drm_modeset_lock mutex; | 712 | struct drm_modeset_lock mutex; |
705 | 713 | ||
@@ -745,6 +753,14 @@ struct drm_crtc { | |||
745 | * @state: | 753 | * @state: |
746 | * | 754 | * |
747 | * Current atomic state for this CRTC. | 755 | * Current atomic state for this CRTC. |
756 | * | ||
757 | * This is protected by @mutex. Note that nonblocking atomic commits | ||
758 | * access the current CRTC state without taking locks. Either by going | ||
759 | * through the &struct drm_atomic_state pointers, see | ||
760 | * for_each_crtc_in_state(), for_each_oldnew_crtc_in_state(), | ||
761 | * for_each_old_crtc_in_state() and for_each_new_crtc_in_state(). Or | ||
762 | * through careful ordering of atomic commit operations as implemented | ||
763 | * in the atomic helpers, see &struct drm_crtc_commit. | ||
748 | */ | 764 | */ |
749 | struct drm_crtc_state *state; | 765 | struct drm_crtc_state *state; |
750 | 766 | ||
diff --git a/include/drm/drm_crtc_helper.h b/include/drm/drm_crtc_helper.h index d026f5017c33..43505c7b2b3f 100644 --- a/include/drm/drm_crtc_helper.h +++ b/include/drm/drm_crtc_helper.h | |||
@@ -43,18 +43,19 @@ | |||
43 | #include <drm/drm_modeset_helper_vtables.h> | 43 | #include <drm/drm_modeset_helper_vtables.h> |
44 | #include <drm/drm_modeset_helper.h> | 44 | #include <drm/drm_modeset_helper.h> |
45 | 45 | ||
46 | extern void drm_helper_disable_unused_functions(struct drm_device *dev); | 46 | void drm_helper_disable_unused_functions(struct drm_device *dev); |
47 | extern int drm_crtc_helper_set_config(struct drm_mode_set *set); | 47 | int drm_crtc_helper_set_config(struct drm_mode_set *set, |
48 | extern bool drm_crtc_helper_set_mode(struct drm_crtc *crtc, | 48 | struct drm_modeset_acquire_ctx *ctx); |
49 | struct drm_display_mode *mode, | 49 | bool drm_crtc_helper_set_mode(struct drm_crtc *crtc, |
50 | int x, int y, | 50 | struct drm_display_mode *mode, |
51 | struct drm_framebuffer *old_fb); | 51 | int x, int y, |
52 | extern bool drm_helper_crtc_in_use(struct drm_crtc *crtc); | 52 | struct drm_framebuffer *old_fb); |
53 | extern bool drm_helper_encoder_in_use(struct drm_encoder *encoder); | 53 | bool drm_helper_crtc_in_use(struct drm_crtc *crtc); |
54 | bool drm_helper_encoder_in_use(struct drm_encoder *encoder); | ||
54 | 55 | ||
55 | extern int drm_helper_connector_dpms(struct drm_connector *connector, int mode); | 56 | int drm_helper_connector_dpms(struct drm_connector *connector, int mode); |
56 | 57 | ||
57 | extern void drm_helper_resume_force_mode(struct drm_device *dev); | 58 | void drm_helper_resume_force_mode(struct drm_device *dev); |
58 | 59 | ||
59 | int drm_helper_crtc_mode_set(struct drm_crtc *crtc, struct drm_display_mode *mode, | 60 | int drm_helper_crtc_mode_set(struct drm_crtc *crtc, struct drm_display_mode *mode, |
60 | struct drm_display_mode *adjusted_mode, int x, int y, | 61 | struct drm_display_mode *adjusted_mode, int x, int y, |
@@ -63,15 +64,15 @@ int drm_helper_crtc_mode_set_base(struct drm_crtc *crtc, int x, int y, | |||
63 | struct drm_framebuffer *old_fb); | 64 | struct drm_framebuffer *old_fb); |
64 | 65 | ||
65 | /* drm_probe_helper.c */ | 66 | /* drm_probe_helper.c */ |
66 | extern int drm_helper_probe_single_connector_modes(struct drm_connector | 67 | int drm_helper_probe_single_connector_modes(struct drm_connector |
67 | *connector, uint32_t maxX, | 68 | *connector, uint32_t maxX, |
68 | uint32_t maxY); | 69 | uint32_t maxY); |
69 | extern void drm_kms_helper_poll_init(struct drm_device *dev); | 70 | void drm_kms_helper_poll_init(struct drm_device *dev); |
70 | extern void drm_kms_helper_poll_fini(struct drm_device *dev); | 71 | void drm_kms_helper_poll_fini(struct drm_device *dev); |
71 | extern bool drm_helper_hpd_irq_event(struct drm_device *dev); | 72 | bool drm_helper_hpd_irq_event(struct drm_device *dev); |
72 | extern void drm_kms_helper_hotplug_event(struct drm_device *dev); | 73 | void drm_kms_helper_hotplug_event(struct drm_device *dev); |
73 | 74 | ||
74 | extern void drm_kms_helper_poll_disable(struct drm_device *dev); | 75 | void drm_kms_helper_poll_disable(struct drm_device *dev); |
75 | extern void drm_kms_helper_poll_enable(struct drm_device *dev); | 76 | void drm_kms_helper_poll_enable(struct drm_device *dev); |
76 | 77 | ||
77 | #endif | 78 | #endif |
diff --git a/include/drm/drm_debugfs.h b/include/drm/drm_debugfs.h new file mode 100644 index 000000000000..ac0f75df1ac9 --- /dev/null +++ b/include/drm/drm_debugfs.h | |||
@@ -0,0 +1,101 @@ | |||
1 | /* | ||
2 | * Internal Header for the Direct Rendering Manager | ||
3 | * | ||
4 | * Copyright 1999 Precision Insight, Inc., Cedar Park, Texas. | ||
5 | * Copyright 2000 VA Linux Systems, Inc., Sunnyvale, California. | ||
6 | * Copyright (c) 2009-2010, Code Aurora Forum. | ||
7 | * All rights reserved. | ||
8 | * | ||
9 | * Author: Rickard E. (Rik) Faith <faith@valinux.com> | ||
10 | * Author: Gareth Hughes <gareth@valinux.com> | ||
11 | * | ||
12 | * Permission is hereby granted, free of charge, to any person obtaining a | ||
13 | * copy of this software and associated documentation files (the "Software"), | ||
14 | * to deal in the Software without restriction, including without limitation | ||
15 | * the rights to use, copy, modify, merge, publish, distribute, sublicense, | ||
16 | * and/or sell copies of the Software, and to permit persons to whom the | ||
17 | * Software is furnished to do so, subject to the following conditions: | ||
18 | * | ||
19 | * The above copyright notice and this permission notice (including the next | ||
20 | * paragraph) shall be included in all copies or substantial portions of the | ||
21 | * Software. | ||
22 | * | ||
23 | * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR | ||
24 | * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, | ||
25 | * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL | ||
26 | * VA LINUX SYSTEMS AND/OR ITS SUPPLIERS BE LIABLE FOR ANY CLAIM, DAMAGES OR | ||
27 | * OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, | ||
28 | * ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR | ||
29 | * OTHER DEALINGS IN THE SOFTWARE. | ||
30 | */ | ||
31 | |||
32 | #ifndef _DRM_DEBUGFS_H_ | ||
33 | #define _DRM_DEBUGFS_H_ | ||
34 | |||
35 | /** | ||
36 | * struct drm_info_list - debugfs info list entry | ||
37 | * | ||
38 | * This structure represents a debugfs file to be created by the drm | ||
39 | * core. | ||
40 | */ | ||
41 | struct drm_info_list { | ||
42 | /** @name: file name */ | ||
43 | const char *name; | ||
44 | /** | ||
45 | * @show: | ||
46 | * | ||
47 | * Show callback. &seq_file->private will be set to the &struct | ||
48 | * drm_info_node corresponding to the instance of this info on a given | ||
49 | * &struct drm_minor. | ||
50 | */ | ||
51 | int (*show)(struct seq_file*, void*); | ||
52 | /** @driver_features: Required driver features for this entry */ | ||
53 | u32 driver_features; | ||
54 | /** @data: Driver-private data, should not be device-specific. */ | ||
55 | void *data; | ||
56 | }; | ||
57 | |||
58 | /** | ||
59 | * struct drm_info_node - Per-minor debugfs node structure | ||
60 | * | ||
61 | * This structure represents a debugfs file, as an instantiation of a &struct | ||
62 | * drm_info_list on a &struct drm_minor. | ||
63 | * | ||
64 | * FIXME: | ||
65 | * | ||
66 | * No it doesn't make a hole lot of sense that we duplicate debugfs entries for | ||
67 | * both the render and the primary nodes, but that's how this has organically | ||
68 | * grown. It should probably be fixed, with a compatibility link, if needed. | ||
69 | */ | ||
70 | struct drm_info_node { | ||
71 | /** @minor: &struct drm_minor for this node. */ | ||
72 | struct drm_minor *minor; | ||
73 | /** @info_ent: template for this node. */ | ||
74 | const struct drm_info_list *info_ent; | ||
75 | /* private: */ | ||
76 | struct list_head list; | ||
77 | struct dentry *dent; | ||
78 | }; | ||
79 | |||
80 | #if defined(CONFIG_DEBUG_FS) | ||
81 | int drm_debugfs_create_files(const struct drm_info_list *files, | ||
82 | int count, struct dentry *root, | ||
83 | struct drm_minor *minor); | ||
84 | int drm_debugfs_remove_files(const struct drm_info_list *files, | ||
85 | int count, struct drm_minor *minor); | ||
86 | #else | ||
87 | static inline int drm_debugfs_create_files(const struct drm_info_list *files, | ||
88 | int count, struct dentry *root, | ||
89 | struct drm_minor *minor) | ||
90 | { | ||
91 | return 0; | ||
92 | } | ||
93 | |||
94 | static inline int drm_debugfs_remove_files(const struct drm_info_list *files, | ||
95 | int count, struct drm_minor *minor) | ||
96 | { | ||
97 | return 0; | ||
98 | } | ||
99 | #endif | ||
100 | |||
101 | #endif /* _DRM_DEBUGFS_H_ */ | ||
diff --git a/include/drm/drm_dp_mst_helper.h b/include/drm/drm_dp_mst_helper.h index f4b4d154b98e..5b024764666c 100644 --- a/include/drm/drm_dp_mst_helper.h +++ b/include/drm/drm_dp_mst_helper.h | |||
@@ -479,18 +479,6 @@ struct drm_dp_mst_topology_mgr { | |||
479 | * @pbn_div: PBN to slots divisor. | 479 | * @pbn_div: PBN to slots divisor. |
480 | */ | 480 | */ |
481 | int pbn_div; | 481 | int pbn_div; |
482 | /** | ||
483 | * @total_slots: Total slots that can be allocated. | ||
484 | */ | ||
485 | int total_slots; | ||
486 | /** | ||
487 | * @avail_slots: Still available slots that can be allocated. | ||
488 | */ | ||
489 | int avail_slots; | ||
490 | /** | ||
491 | * @total_pbn: Total PBN count. | ||
492 | */ | ||
493 | int total_pbn; | ||
494 | 482 | ||
495 | /** | 483 | /** |
496 | * @qlock: protects @tx_msg_downq, the &drm_dp_mst_branch.txslost and | 484 | * @qlock: protects @tx_msg_downq, the &drm_dp_mst_branch.txslost and |
@@ -579,7 +567,8 @@ struct edid *drm_dp_mst_get_edid(struct drm_connector *connector, struct drm_dp_ | |||
579 | int drm_dp_calc_pbn_mode(int clock, int bpp); | 567 | int drm_dp_calc_pbn_mode(int clock, int bpp); |
580 | 568 | ||
581 | 569 | ||
582 | bool drm_dp_mst_allocate_vcpi(struct drm_dp_mst_topology_mgr *mgr, struct drm_dp_mst_port *port, int pbn, int *slots); | 570 | bool drm_dp_mst_allocate_vcpi(struct drm_dp_mst_topology_mgr *mgr, |
571 | struct drm_dp_mst_port *port, int pbn, int slots); | ||
583 | 572 | ||
584 | int drm_dp_mst_get_vcpi_slots(struct drm_dp_mst_topology_mgr *mgr, struct drm_dp_mst_port *port); | 573 | int drm_dp_mst_get_vcpi_slots(struct drm_dp_mst_topology_mgr *mgr, struct drm_dp_mst_port *port); |
585 | 574 | ||
diff --git a/include/drm/drm_drv.h b/include/drm/drm_drv.h index 8f900fb30275..53b98321df9b 100644 --- a/include/drm/drm_drv.h +++ b/include/drm/drm_drv.h | |||
@@ -522,11 +522,11 @@ struct drm_driver { | |||
522 | int dev_priv_size; | 522 | int dev_priv_size; |
523 | }; | 523 | }; |
524 | 524 | ||
525 | extern __printf(6, 7) | 525 | __printf(6, 7) |
526 | void drm_dev_printk(const struct device *dev, const char *level, | 526 | void drm_dev_printk(const struct device *dev, const char *level, |
527 | unsigned int category, const char *function_name, | 527 | unsigned int category, const char *function_name, |
528 | const char *prefix, const char *format, ...); | 528 | const char *prefix, const char *format, ...); |
529 | extern __printf(3, 4) | 529 | __printf(3, 4) |
530 | void drm_printk(const char *level, unsigned int category, | 530 | void drm_printk(const char *level, unsigned int category, |
531 | const char *format, ...); | 531 | const char *format, ...); |
532 | extern unsigned int drm_debug; | 532 | extern unsigned int drm_debug; |
diff --git a/include/drm/drm_fourcc.h b/include/drm/drm_fourcc.h index fcc08da850c8..6942e84b6edd 100644 --- a/include/drm/drm_fourcc.h +++ b/include/drm/drm_fourcc.h | |||
@@ -25,6 +25,9 @@ | |||
25 | #include <linux/types.h> | 25 | #include <linux/types.h> |
26 | #include <uapi/drm/drm_fourcc.h> | 26 | #include <uapi/drm/drm_fourcc.h> |
27 | 27 | ||
28 | struct drm_device; | ||
29 | struct drm_mode_fb_cmd2; | ||
30 | |||
28 | /** | 31 | /** |
29 | * struct drm_format_info - information about a DRM format | 32 | * struct drm_format_info - information about a DRM format |
30 | * @format: 4CC format identifier (DRM_FORMAT_*) | 33 | * @format: 4CC format identifier (DRM_FORMAT_*) |
@@ -55,6 +58,9 @@ struct drm_format_name_buf { | |||
55 | 58 | ||
56 | const struct drm_format_info *__drm_format_info(u32 format); | 59 | const struct drm_format_info *__drm_format_info(u32 format); |
57 | const struct drm_format_info *drm_format_info(u32 format); | 60 | const struct drm_format_info *drm_format_info(u32 format); |
61 | const struct drm_format_info * | ||
62 | drm_get_format_info(struct drm_device *dev, | ||
63 | const struct drm_mode_fb_cmd2 *mode_cmd); | ||
58 | uint32_t drm_mode_legacy_fb_format(uint32_t bpp, uint32_t depth); | 64 | uint32_t drm_mode_legacy_fb_format(uint32_t bpp, uint32_t depth); |
59 | int drm_format_num_planes(uint32_t format); | 65 | int drm_format_num_planes(uint32_t format); |
60 | int drm_format_plane_cpp(uint32_t format, int plane); | 66 | int drm_format_plane_cpp(uint32_t format, int plane); |
diff --git a/include/drm/drm_global.h b/include/drm/drm_global.h index a06805eaf649..3a830602a2e4 100644 --- a/include/drm/drm_global.h +++ b/include/drm/drm_global.h | |||
@@ -45,9 +45,9 @@ struct drm_global_reference { | |||
45 | void (*release) (struct drm_global_reference *); | 45 | void (*release) (struct drm_global_reference *); |
46 | }; | 46 | }; |
47 | 47 | ||
48 | extern void drm_global_init(void); | 48 | void drm_global_init(void); |
49 | extern void drm_global_release(void); | 49 | void drm_global_release(void); |
50 | extern int drm_global_item_ref(struct drm_global_reference *ref); | 50 | int drm_global_item_ref(struct drm_global_reference *ref); |
51 | extern void drm_global_item_unref(struct drm_global_reference *ref); | 51 | void drm_global_item_unref(struct drm_global_reference *ref); |
52 | 52 | ||
53 | #endif | 53 | #endif |
diff --git a/include/drm/drm_hashtab.h b/include/drm/drm_hashtab.h index fce2ef3fdfff..bb95ff011baf 100644 --- a/include/drm/drm_hashtab.h +++ b/include/drm/drm_hashtab.h | |||
@@ -49,17 +49,17 @@ struct drm_open_hash { | |||
49 | u8 order; | 49 | u8 order; |
50 | }; | 50 | }; |
51 | 51 | ||
52 | extern int drm_ht_create(struct drm_open_hash *ht, unsigned int order); | 52 | int drm_ht_create(struct drm_open_hash *ht, unsigned int order); |
53 | extern int drm_ht_insert_item(struct drm_open_hash *ht, struct drm_hash_item *item); | 53 | int drm_ht_insert_item(struct drm_open_hash *ht, struct drm_hash_item *item); |
54 | extern int drm_ht_just_insert_please(struct drm_open_hash *ht, struct drm_hash_item *item, | 54 | int drm_ht_just_insert_please(struct drm_open_hash *ht, struct drm_hash_item *item, |
55 | unsigned long seed, int bits, int shift, | 55 | unsigned long seed, int bits, int shift, |
56 | unsigned long add); | 56 | unsigned long add); |
57 | extern int drm_ht_find_item(struct drm_open_hash *ht, unsigned long key, struct drm_hash_item **item); | 57 | int drm_ht_find_item(struct drm_open_hash *ht, unsigned long key, struct drm_hash_item **item); |
58 | 58 | ||
59 | extern void drm_ht_verbose_list(struct drm_open_hash *ht, unsigned long key); | 59 | void drm_ht_verbose_list(struct drm_open_hash *ht, unsigned long key); |
60 | extern int drm_ht_remove_key(struct drm_open_hash *ht, unsigned long key); | 60 | int drm_ht_remove_key(struct drm_open_hash *ht, unsigned long key); |
61 | extern int drm_ht_remove_item(struct drm_open_hash *ht, struct drm_hash_item *item); | 61 | int drm_ht_remove_item(struct drm_open_hash *ht, struct drm_hash_item *item); |
62 | extern void drm_ht_remove(struct drm_open_hash *ht); | 62 | void drm_ht_remove(struct drm_open_hash *ht); |
63 | 63 | ||
64 | /* | 64 | /* |
65 | * RCU-safe interface | 65 | * RCU-safe interface |
diff --git a/include/drm/drm_ioctl.h b/include/drm/drm_ioctl.h new file mode 100644 index 000000000000..f17ee077f649 --- /dev/null +++ b/include/drm/drm_ioctl.h | |||
@@ -0,0 +1,102 @@ | |||
1 | /* | ||
2 | * Internal Header for the Direct Rendering Manager | ||
3 | * | ||
4 | * Copyright 1999 Precision Insight, Inc., Cedar Park, Texas. | ||
5 | * Copyright 2000 VA Linux Systems, Inc., Sunnyvale, California. | ||
6 | * Copyright (c) 2009-2010, Code Aurora Forum. | ||
7 | * All rights reserved. | ||
8 | * | ||
9 | * Author: Rickard E. (Rik) Faith <faith@valinux.com> | ||
10 | * Author: Gareth Hughes <gareth@valinux.com> | ||
11 | * | ||
12 | * Permission is hereby granted, free of charge, to any person obtaining a | ||
13 | * copy of this software and associated documentation files (the "Software"), | ||
14 | * to deal in the Software without restriction, including without limitation | ||
15 | * the rights to use, copy, modify, merge, publish, distribute, sublicense, | ||
16 | * and/or sell copies of the Software, and to permit persons to whom the | ||
17 | * Software is furnished to do so, subject to the following conditions: | ||
18 | * | ||
19 | * The above copyright notice and this permission notice (including the next | ||
20 | * paragraph) shall be included in all copies or substantial portions of the | ||
21 | * Software. | ||
22 | * | ||
23 | * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR | ||
24 | * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, | ||
25 | * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL | ||
26 | * VA LINUX SYSTEMS AND/OR ITS SUPPLIERS BE LIABLE FOR ANY CLAIM, DAMAGES OR | ||
27 | * OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, | ||
28 | * ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR | ||
29 | * OTHER DEALINGS IN THE SOFTWARE. | ||
30 | */ | ||
31 | |||
32 | #ifndef _DRM_IOCTL_H_ | ||
33 | #define _DRM_IOCTL_H_ | ||
34 | |||
35 | #include <linux/types.h> | ||
36 | |||
37 | #include <asm/ioctl.h> | ||
38 | |||
39 | struct drm_device; | ||
40 | struct drm_file; | ||
41 | struct file; | ||
42 | |||
43 | /** | ||
44 | * Ioctl function type. | ||
45 | * | ||
46 | * \param inode device inode. | ||
47 | * \param file_priv DRM file private pointer. | ||
48 | * \param cmd command. | ||
49 | * \param arg argument. | ||
50 | */ | ||
51 | typedef int drm_ioctl_t(struct drm_device *dev, void *data, | ||
52 | struct drm_file *file_priv); | ||
53 | |||
54 | typedef int drm_ioctl_compat_t(struct file *filp, unsigned int cmd, | ||
55 | unsigned long arg); | ||
56 | |||
57 | #define DRM_IOCTL_NR(n) _IOC_NR(n) | ||
58 | #define DRM_MAJOR 226 | ||
59 | |||
60 | #define DRM_AUTH 0x1 | ||
61 | #define DRM_MASTER 0x2 | ||
62 | #define DRM_ROOT_ONLY 0x4 | ||
63 | #define DRM_CONTROL_ALLOW 0x8 | ||
64 | #define DRM_UNLOCKED 0x10 | ||
65 | #define DRM_RENDER_ALLOW 0x20 | ||
66 | |||
67 | struct drm_ioctl_desc { | ||
68 | unsigned int cmd; | ||
69 | int flags; | ||
70 | drm_ioctl_t *func; | ||
71 | const char *name; | ||
72 | }; | ||
73 | |||
74 | /** | ||
75 | * Creates a driver or general drm_ioctl_desc array entry for the given | ||
76 | * ioctl, for use by drm_ioctl(). | ||
77 | */ | ||
78 | |||
79 | #define DRM_IOCTL_DEF_DRV(ioctl, _func, _flags) \ | ||
80 | [DRM_IOCTL_NR(DRM_IOCTL_##ioctl) - DRM_COMMAND_BASE] = { \ | ||
81 | .cmd = DRM_IOCTL_##ioctl, \ | ||
82 | .func = _func, \ | ||
83 | .flags = _flags, \ | ||
84 | .name = #ioctl \ | ||
85 | } | ||
86 | |||
87 | int drm_ioctl_permit(u32 flags, struct drm_file *file_priv); | ||
88 | long drm_ioctl(struct file *filp, unsigned int cmd, unsigned long arg); | ||
89 | #ifdef CONFIG_COMPAT | ||
90 | long drm_compat_ioctl(struct file *filp, unsigned int cmd, unsigned long arg); | ||
91 | #else | ||
92 | /* Let drm_compat_ioctl be assigned to .compat_ioctl unconditionally */ | ||
93 | #define drm_compat_ioctl NULL | ||
94 | #endif | ||
95 | bool drm_ioctl_flags(unsigned int nr, unsigned int *flags); | ||
96 | |||
97 | int drm_noop(struct drm_device *dev, void *data, | ||
98 | struct drm_file *file_priv); | ||
99 | int drm_invalid_op(struct drm_device *dev, void *data, | ||
100 | struct drm_file *file_priv); | ||
101 | |||
102 | #endif /* _DRM_IOCTL_H_ */ | ||
diff --git a/include/drm/drm_mode_config.h b/include/drm/drm_mode_config.h index ea169a90b3c4..42981711189b 100644 --- a/include/drm/drm_mode_config.h +++ b/include/drm/drm_mode_config.h | |||
@@ -34,6 +34,7 @@ struct drm_file; | |||
34 | struct drm_device; | 34 | struct drm_device; |
35 | struct drm_atomic_state; | 35 | struct drm_atomic_state; |
36 | struct drm_mode_fb_cmd2; | 36 | struct drm_mode_fb_cmd2; |
37 | struct drm_format_info; | ||
37 | 38 | ||
38 | /** | 39 | /** |
39 | * struct drm_mode_config_funcs - basic driver provided mode setting functions | 40 | * struct drm_mode_config_funcs - basic driver provided mode setting functions |
@@ -70,6 +71,19 @@ struct drm_mode_config_funcs { | |||
70 | const struct drm_mode_fb_cmd2 *mode_cmd); | 71 | const struct drm_mode_fb_cmd2 *mode_cmd); |
71 | 72 | ||
72 | /** | 73 | /** |
74 | * @get_format_info: | ||
75 | * | ||
76 | * Allows a driver to return custom format information for special | ||
77 | * fb layouts (eg. ones with auxiliary compression control planes). | ||
78 | * | ||
79 | * RETURNS: | ||
80 | * | ||
81 | * The format information specific to the given fb metadata, or | ||
82 | * NULL if none is found. | ||
83 | */ | ||
84 | const struct drm_format_info *(*get_format_info)(const struct drm_mode_fb_cmd2 *mode_cmd); | ||
85 | |||
86 | /** | ||
73 | * @output_poll_changed: | 87 | * @output_poll_changed: |
74 | * | 88 | * |
75 | * Callback used by helpers to inform the driver of output configuration | 89 | * Callback used by helpers to inform the driver of output configuration |
@@ -293,21 +307,6 @@ struct drm_mode_config_funcs { | |||
293 | 307 | ||
294 | /** | 308 | /** |
295 | * struct drm_mode_config - Mode configuration control structure | 309 | * struct drm_mode_config - Mode configuration control structure |
296 | * @mutex: mutex protecting KMS related lists and structures | ||
297 | * @connection_mutex: ww mutex protecting connector state and routing | ||
298 | * @acquire_ctx: global implicit acquire context used by atomic drivers for | ||
299 | * legacy IOCTLs | ||
300 | * @fb_lock: mutex to protect fb state and lists | ||
301 | * @num_fb: number of fbs available | ||
302 | * @fb_list: list of framebuffers available | ||
303 | * @num_encoder: number of encoders on this device | ||
304 | * @encoder_list: list of encoder objects | ||
305 | * @num_overlay_plane: number of overlay planes on this device | ||
306 | * @num_total_plane: number of universal (i.e. with primary/curso) planes on this device | ||
307 | * @plane_list: list of plane objects | ||
308 | * @num_crtc: number of CRTCs on this device | ||
309 | * @crtc_list: list of CRTC objects | ||
310 | * @property_list: list of property objects | ||
311 | * @min_width: minimum pixel width on this device | 310 | * @min_width: minimum pixel width on this device |
312 | * @min_height: minimum pixel height on this device | 311 | * @min_height: minimum pixel height on this device |
313 | * @max_width: maximum pixel width on this device | 312 | * @max_width: maximum pixel width on this device |
@@ -318,9 +317,6 @@ struct drm_mode_config_funcs { | |||
318 | * @poll_running: track polling status for this device | 317 | * @poll_running: track polling status for this device |
319 | * @delayed_event: track delayed poll uevent deliver for this device | 318 | * @delayed_event: track delayed poll uevent deliver for this device |
320 | * @output_poll_work: delayed work for polling in process context | 319 | * @output_poll_work: delayed work for polling in process context |
321 | * @property_blob_list: list of all the blob property objects | ||
322 | * @blob_lock: mutex for blob property allocation and management | ||
323 | * @*_property: core property tracking | ||
324 | * @preferred_depth: preferred RBG pixel depth, used by fb helpers | 320 | * @preferred_depth: preferred RBG pixel depth, used by fb helpers |
325 | * @prefer_shadow: hint to userspace to prefer shadow-fb rendering | 321 | * @prefer_shadow: hint to userspace to prefer shadow-fb rendering |
326 | * @cursor_width: hint to userspace for max cursor width | 322 | * @cursor_width: hint to userspace for max cursor width |
@@ -332,9 +328,37 @@ struct drm_mode_config_funcs { | |||
332 | * global restrictions are also here, e.g. dimension restrictions. | 328 | * global restrictions are also here, e.g. dimension restrictions. |
333 | */ | 329 | */ |
334 | struct drm_mode_config { | 330 | struct drm_mode_config { |
335 | struct mutex mutex; /* protects configuration (mode lists etc.) */ | 331 | /** |
336 | struct drm_modeset_lock connection_mutex; /* protects connector->encoder and encoder->crtc links */ | 332 | * @mutex: |
337 | struct drm_modeset_acquire_ctx *acquire_ctx; /* for legacy _lock_all() / _unlock_all() */ | 333 | * |
334 | * This is the big scary modeset BKL which protects everything that | ||
335 | * isn't protect otherwise. Scope is unclear and fuzzy, try to remove | ||
336 | * anything from under it's protection and move it into more well-scoped | ||
337 | * locks. | ||
338 | * | ||
339 | * The one important thing this protects is the use of @acquire_ctx. | ||
340 | */ | ||
341 | struct mutex mutex; | ||
342 | |||
343 | /** | ||
344 | * @connection_mutex: | ||
345 | * | ||
346 | * This protects connector state and the connector to encoder to CRTC | ||
347 | * routing chain. | ||
348 | * | ||
349 | * For atomic drivers specifically this protects &drm_connector.state. | ||
350 | */ | ||
351 | struct drm_modeset_lock connection_mutex; | ||
352 | |||
353 | /** | ||
354 | * @acquire_ctx: | ||
355 | * | ||
356 | * Global implicit acquire context used by atomic drivers for legacy | ||
357 | * IOCTLs. Deprecated, since implicit locking contexts make it | ||
358 | * impossible to use driver-private &struct drm_modeset_lock. Users of | ||
359 | * this must hold @mutex. | ||
360 | */ | ||
361 | struct drm_modeset_acquire_ctx *acquire_ctx; | ||
338 | 362 | ||
339 | /** | 363 | /** |
340 | * @idr_mutex: | 364 | * @idr_mutex: |
@@ -360,8 +384,11 @@ struct drm_mode_config { | |||
360 | */ | 384 | */ |
361 | struct idr tile_idr; | 385 | struct idr tile_idr; |
362 | 386 | ||
363 | struct mutex fb_lock; /* proctects global and per-file fb lists */ | 387 | /** @fb_lock: Mutex to protect fb the global @fb_list and @num_fb. */ |
388 | struct mutex fb_lock; | ||
389 | /** @num_fb: Number of entries on @fb_list. */ | ||
364 | int num_fb; | 390 | int num_fb; |
391 | /** @fb_list: List of all &struct drm_framebuffer. */ | ||
365 | struct list_head fb_list; | 392 | struct list_head fb_list; |
366 | 393 | ||
367 | /** | 394 | /** |
@@ -379,27 +406,80 @@ struct drm_mode_config { | |||
379 | */ | 406 | */ |
380 | struct ida connector_ida; | 407 | struct ida connector_ida; |
381 | /** | 408 | /** |
382 | * @connector_list: List of connector objects. Protected by | 409 | * @connector_list: |
383 | * @connector_list_lock. Only use drm_for_each_connector_iter() and | 410 | * |
411 | * List of connector objects linked with &drm_connector.head. Protected | ||
412 | * by @connector_list_lock. Only use drm_for_each_connector_iter() and | ||
384 | * &struct drm_connector_list_iter to walk this list. | 413 | * &struct drm_connector_list_iter to walk this list. |
385 | */ | 414 | */ |
386 | struct list_head connector_list; | 415 | struct list_head connector_list; |
416 | /** | ||
417 | * @num_encoder: | ||
418 | * | ||
419 | * Number of encoders on this device. This is invariant over the | ||
420 | * lifetime of a device and hence doesn't need any locks. | ||
421 | */ | ||
387 | int num_encoder; | 422 | int num_encoder; |
423 | /** | ||
424 | * @encoder_list: | ||
425 | * | ||
426 | * List of encoder objects linked with &drm_encoder.head. This is | ||
427 | * invariant over the lifetime of a device and hence doesn't need any | ||
428 | * locks. | ||
429 | */ | ||
388 | struct list_head encoder_list; | 430 | struct list_head encoder_list; |
389 | 431 | ||
390 | /* | 432 | /** |
391 | * Track # of overlay planes separately from # of total planes. By | 433 | * @num_overlay_plane: |
392 | * default we only advertise overlay planes to userspace; if userspace | 434 | * |
393 | * sets the "universal plane" capability bit, we'll go ahead and | 435 | * Number of overlay planes on this device, excluding primary and cursor |
394 | * expose all planes. | 436 | * planes. |
437 | * | ||
438 | * Track number of overlay planes separately from number of total | ||
439 | * planes. By default we only advertise overlay planes to userspace; if | ||
440 | * userspace sets the "universal plane" capability bit, we'll go ahead | ||
441 | * and expose all planes. This is invariant over the lifetime of a | ||
442 | * device and hence doesn't need any locks. | ||
395 | */ | 443 | */ |
396 | int num_overlay_plane; | 444 | int num_overlay_plane; |
445 | /** | ||
446 | * @num_total_plane: | ||
447 | * | ||
448 | * Number of universal (i.e. with primary/curso) planes on this device. | ||
449 | * This is invariant over the lifetime of a device and hence doesn't | ||
450 | * need any locks. | ||
451 | */ | ||
397 | int num_total_plane; | 452 | int num_total_plane; |
453 | /** | ||
454 | * @plane_list: | ||
455 | * | ||
456 | * List of plane objects linked with &drm_plane.head. This is invariant | ||
457 | * over the lifetime of a device and hence doesn't need any locks. | ||
458 | */ | ||
398 | struct list_head plane_list; | 459 | struct list_head plane_list; |
399 | 460 | ||
461 | /** | ||
462 | * @num_crtc: | ||
463 | * | ||
464 | * Number of CRTCs on this device linked with &drm_crtc.head. This is invariant over the lifetime | ||
465 | * of a device and hence doesn't need any locks. | ||
466 | */ | ||
400 | int num_crtc; | 467 | int num_crtc; |
468 | /** | ||
469 | * @crtc_list: | ||
470 | * | ||
471 | * List of CRTC objects linked with &drm_crtc.head. This is invariant | ||
472 | * over the lifetime of a device and hence doesn't need any locks. | ||
473 | */ | ||
401 | struct list_head crtc_list; | 474 | struct list_head crtc_list; |
402 | 475 | ||
476 | /** | ||
477 | * @property_list: | ||
478 | * | ||
479 | * List of property type objects linked with &drm_property.head. This is | ||
480 | * invariant over the lifetime of a device and hence doesn't need any | ||
481 | * locks. | ||
482 | */ | ||
403 | struct list_head property_list; | 483 | struct list_head property_list; |
404 | 484 | ||
405 | int min_width, min_height; | 485 | int min_width, min_height; |
@@ -413,10 +493,24 @@ struct drm_mode_config { | |||
413 | bool delayed_event; | 493 | bool delayed_event; |
414 | struct delayed_work output_poll_work; | 494 | struct delayed_work output_poll_work; |
415 | 495 | ||
496 | /** | ||
497 | * @blob_lock: | ||
498 | * | ||
499 | * Mutex for blob property allocation and management, protects | ||
500 | * @property_blob_list and &drm_file.blobs. | ||
501 | */ | ||
416 | struct mutex blob_lock; | 502 | struct mutex blob_lock; |
417 | 503 | ||
418 | /* pointers to standard properties */ | 504 | /** |
505 | * @property_blob_list: | ||
506 | * | ||
507 | * List of all the blob property objects linked with | ||
508 | * &drm_property_blob.head. Protected by @blob_lock. | ||
509 | */ | ||
419 | struct list_head property_blob_list; | 510 | struct list_head property_blob_list; |
511 | |||
512 | /* pointers to standard properties */ | ||
513 | |||
420 | /** | 514 | /** |
421 | * @edid_property: Default connector property to hold the EDID of the | 515 | * @edid_property: Default connector property to hold the EDID of the |
422 | * currently connected sink, if any. | 516 | * currently connected sink, if any. |
diff --git a/include/drm/drm_of.h b/include/drm/drm_of.h index 26a64805cc15..d1fc563f068a 100644 --- a/include/drm/drm_of.h +++ b/include/drm/drm_of.h | |||
@@ -11,18 +11,18 @@ struct drm_encoder; | |||
11 | struct device_node; | 11 | struct device_node; |
12 | 12 | ||
13 | #ifdef CONFIG_OF | 13 | #ifdef CONFIG_OF |
14 | extern uint32_t drm_of_find_possible_crtcs(struct drm_device *dev, | 14 | uint32_t drm_of_find_possible_crtcs(struct drm_device *dev, |
15 | struct device_node *port); | 15 | struct device_node *port); |
16 | extern void drm_of_component_match_add(struct device *master, | 16 | void drm_of_component_match_add(struct device *master, |
17 | struct component_match **matchptr, | 17 | struct component_match **matchptr, |
18 | int (*compare)(struct device *, void *), | 18 | int (*compare)(struct device *, void *), |
19 | struct device_node *node); | 19 | struct device_node *node); |
20 | extern int drm_of_component_probe(struct device *dev, | 20 | int drm_of_component_probe(struct device *dev, |
21 | int (*compare_of)(struct device *, void *), | 21 | int (*compare_of)(struct device *, void *), |
22 | const struct component_master_ops *m_ops); | 22 | const struct component_master_ops *m_ops); |
23 | extern int drm_of_encoder_active_endpoint(struct device_node *node, | 23 | int drm_of_encoder_active_endpoint(struct device_node *node, |
24 | struct drm_encoder *encoder, | 24 | struct drm_encoder *encoder, |
25 | struct of_endpoint *endpoint); | 25 | struct of_endpoint *endpoint); |
26 | #else | 26 | #else |
27 | static inline uint32_t drm_of_find_possible_crtcs(struct drm_device *dev, | 27 | static inline uint32_t drm_of_find_possible_crtcs(struct drm_device *dev, |
28 | struct device_node *port) | 28 | struct device_node *port) |
diff --git a/include/drm/drm_pci.h b/include/drm/drm_pci.h index f5ebfcaf69e0..4579fac1080c 100644 --- a/include/drm/drm_pci.h +++ b/include/drm/drm_pci.h | |||
@@ -39,17 +39,17 @@ struct drm_device; | |||
39 | struct drm_driver; | 39 | struct drm_driver; |
40 | struct drm_master; | 40 | struct drm_master; |
41 | 41 | ||
42 | extern struct drm_dma_handle *drm_pci_alloc(struct drm_device *dev, size_t size, | 42 | struct drm_dma_handle *drm_pci_alloc(struct drm_device *dev, size_t size, |
43 | size_t align); | 43 | size_t align); |
44 | extern void drm_pci_free(struct drm_device *dev, struct drm_dma_handle * dmah); | 44 | void drm_pci_free(struct drm_device *dev, struct drm_dma_handle * dmah); |
45 | 45 | ||
46 | extern int drm_pci_init(struct drm_driver *driver, struct pci_driver *pdriver); | 46 | int drm_pci_init(struct drm_driver *driver, struct pci_driver *pdriver); |
47 | extern void drm_pci_exit(struct drm_driver *driver, struct pci_driver *pdriver); | 47 | void drm_pci_exit(struct drm_driver *driver, struct pci_driver *pdriver); |
48 | #ifdef CONFIG_PCI | 48 | #ifdef CONFIG_PCI |
49 | extern int drm_get_pci_dev(struct pci_dev *pdev, | 49 | int drm_get_pci_dev(struct pci_dev *pdev, |
50 | const struct pci_device_id *ent, | 50 | const struct pci_device_id *ent, |
51 | struct drm_driver *driver); | 51 | struct drm_driver *driver); |
52 | extern int drm_pci_set_busid(struct drm_device *dev, struct drm_master *master); | 52 | int drm_pci_set_busid(struct drm_device *dev, struct drm_master *master); |
53 | #else | 53 | #else |
54 | static inline int drm_get_pci_dev(struct pci_dev *pdev, | 54 | static inline int drm_get_pci_dev(struct pci_dev *pdev, |
55 | const struct pci_device_id *ent, | 55 | const struct pci_device_id *ent, |
@@ -69,7 +69,7 @@ static inline int drm_pci_set_busid(struct drm_device *dev, | |||
69 | #define DRM_PCIE_SPEED_50 2 | 69 | #define DRM_PCIE_SPEED_50 2 |
70 | #define DRM_PCIE_SPEED_80 4 | 70 | #define DRM_PCIE_SPEED_80 4 |
71 | 71 | ||
72 | extern int drm_pcie_get_speed_cap_mask(struct drm_device *dev, u32 *speed_mask); | 72 | int drm_pcie_get_speed_cap_mask(struct drm_device *dev, u32 *speed_mask); |
73 | extern int drm_pcie_get_max_link_width(struct drm_device *dev, u32 *mlw); | 73 | int drm_pcie_get_max_link_width(struct drm_device *dev, u32 *mlw); |
74 | 74 | ||
75 | #endif /* _DRM_PCI_H_ */ | 75 | #endif /* _DRM_PCI_H_ */ |
diff --git a/include/drm/drm_plane.h b/include/drm/drm_plane.h index 20867b4371ab..9ab3e7044812 100644 --- a/include/drm/drm_plane.h +++ b/include/drm/drm_plane.h | |||
@@ -29,6 +29,7 @@ | |||
29 | 29 | ||
30 | struct drm_crtc; | 30 | struct drm_crtc; |
31 | struct drm_printer; | 31 | struct drm_printer; |
32 | struct drm_modeset_acquire_ctx; | ||
32 | 33 | ||
33 | /** | 34 | /** |
34 | * struct drm_plane_state - mutable plane state | 35 | * struct drm_plane_state - mutable plane state |
@@ -184,7 +185,8 @@ struct drm_plane_funcs { | |||
184 | int crtc_x, int crtc_y, | 185 | int crtc_x, int crtc_y, |
185 | unsigned int crtc_w, unsigned int crtc_h, | 186 | unsigned int crtc_w, unsigned int crtc_h, |
186 | uint32_t src_x, uint32_t src_y, | 187 | uint32_t src_x, uint32_t src_y, |
187 | uint32_t src_w, uint32_t src_h); | 188 | uint32_t src_w, uint32_t src_h, |
189 | struct drm_modeset_acquire_ctx *ctx); | ||
188 | 190 | ||
189 | /** | 191 | /** |
190 | * @disable_plane: | 192 | * @disable_plane: |
@@ -201,7 +203,8 @@ struct drm_plane_funcs { | |||
201 | * | 203 | * |
202 | * 0 on success or a negative error code on failure. | 204 | * 0 on success or a negative error code on failure. |
203 | */ | 205 | */ |
204 | int (*disable_plane)(struct drm_plane *plane); | 206 | int (*disable_plane)(struct drm_plane *plane, |
207 | struct drm_modeset_acquire_ctx *ctx); | ||
205 | 208 | ||
206 | /** | 209 | /** |
207 | * @destroy: | 210 | * @destroy: |
@@ -456,7 +459,6 @@ enum drm_plane_type { | |||
456 | * @funcs: helper functions | 459 | * @funcs: helper functions |
457 | * @properties: property tracking for this plane | 460 | * @properties: property tracking for this plane |
458 | * @type: type of plane (overlay, primary, cursor) | 461 | * @type: type of plane (overlay, primary, cursor) |
459 | * @state: current atomic state for this plane | ||
460 | * @zpos_property: zpos property for this plane | 462 | * @zpos_property: zpos property for this plane |
461 | * @rotation_property: rotation property for this plane | 463 | * @rotation_property: rotation property for this plane |
462 | * @helper_private: mid-layer private data | 464 | * @helper_private: mid-layer private data |
@@ -473,6 +475,8 @@ struct drm_plane { | |||
473 | * Protects modeset plane state, together with the &drm_crtc.mutex of | 475 | * Protects modeset plane state, together with the &drm_crtc.mutex of |
474 | * CRTC this plane is linked to (when active, getting activated or | 476 | * CRTC this plane is linked to (when active, getting activated or |
475 | * getting disabled). | 477 | * getting disabled). |
478 | * | ||
479 | * For atomic drivers specifically this protects @state. | ||
476 | */ | 480 | */ |
477 | struct drm_modeset_lock mutex; | 481 | struct drm_modeset_lock mutex; |
478 | 482 | ||
@@ -502,6 +506,19 @@ struct drm_plane { | |||
502 | 506 | ||
503 | const struct drm_plane_helper_funcs *helper_private; | 507 | const struct drm_plane_helper_funcs *helper_private; |
504 | 508 | ||
509 | /** | ||
510 | * @state: | ||
511 | * | ||
512 | * Current atomic state for this plane. | ||
513 | * | ||
514 | * This is protected by @mutex. Note that nonblocking atomic commits | ||
515 | * access the current plane state without taking locks. Either by going | ||
516 | * through the &struct drm_atomic_state pointers, see | ||
517 | * for_each_plane_in_state(), for_each_oldnew_plane_in_state(), | ||
518 | * for_each_old_plane_in_state() and for_each_new_plane_in_state(). Or | ||
519 | * through careful ordering of atomic commit operations as implemented | ||
520 | * in the atomic helpers, see &struct drm_crtc_commit. | ||
521 | */ | ||
505 | struct drm_plane_state *state; | 522 | struct drm_plane_state *state; |
506 | 523 | ||
507 | struct drm_property *zpos_property; | 524 | struct drm_property *zpos_property; |
@@ -510,7 +527,7 @@ struct drm_plane { | |||
510 | 527 | ||
511 | #define obj_to_plane(x) container_of(x, struct drm_plane, base) | 528 | #define obj_to_plane(x) container_of(x, struct drm_plane, base) |
512 | 529 | ||
513 | extern __printf(8, 9) | 530 | __printf(8, 9) |
514 | int drm_universal_plane_init(struct drm_device *dev, | 531 | int drm_universal_plane_init(struct drm_device *dev, |
515 | struct drm_plane *plane, | 532 | struct drm_plane *plane, |
516 | uint32_t possible_crtcs, | 533 | uint32_t possible_crtcs, |
@@ -519,13 +536,13 @@ int drm_universal_plane_init(struct drm_device *dev, | |||
519 | unsigned int format_count, | 536 | unsigned int format_count, |
520 | enum drm_plane_type type, | 537 | enum drm_plane_type type, |
521 | const char *name, ...); | 538 | const char *name, ...); |
522 | extern int drm_plane_init(struct drm_device *dev, | 539 | int drm_plane_init(struct drm_device *dev, |
523 | struct drm_plane *plane, | 540 | struct drm_plane *plane, |
524 | uint32_t possible_crtcs, | 541 | uint32_t possible_crtcs, |
525 | const struct drm_plane_funcs *funcs, | 542 | const struct drm_plane_funcs *funcs, |
526 | const uint32_t *formats, unsigned int format_count, | 543 | const uint32_t *formats, unsigned int format_count, |
527 | bool is_primary); | 544 | bool is_primary); |
528 | extern void drm_plane_cleanup(struct drm_plane *plane); | 545 | void drm_plane_cleanup(struct drm_plane *plane); |
529 | 546 | ||
530 | /** | 547 | /** |
531 | * drm_plane_index - find the index of a registered plane | 548 | * drm_plane_index - find the index of a registered plane |
@@ -538,8 +555,8 @@ static inline unsigned int drm_plane_index(struct drm_plane *plane) | |||
538 | { | 555 | { |
539 | return plane->index; | 556 | return plane->index; |
540 | } | 557 | } |
541 | extern struct drm_plane * drm_plane_from_index(struct drm_device *dev, int idx); | 558 | struct drm_plane * drm_plane_from_index(struct drm_device *dev, int idx); |
542 | extern void drm_plane_force_disable(struct drm_plane *plane); | 559 | void drm_plane_force_disable(struct drm_plane *plane); |
543 | 560 | ||
544 | int drm_mode_plane_set_obj_prop(struct drm_plane *plane, | 561 | int drm_mode_plane_set_obj_prop(struct drm_plane *plane, |
545 | struct drm_property *property, | 562 | struct drm_property *property, |
diff --git a/include/drm/drm_plane_helper.h b/include/drm/drm_plane_helper.h index c18959685c06..7c8a00ceadb7 100644 --- a/include/drm/drm_plane_helper.h +++ b/include/drm/drm_plane_helper.h | |||
@@ -61,8 +61,10 @@ int drm_primary_helper_update(struct drm_plane *plane, | |||
61 | int crtc_x, int crtc_y, | 61 | int crtc_x, int crtc_y, |
62 | unsigned int crtc_w, unsigned int crtc_h, | 62 | unsigned int crtc_w, unsigned int crtc_h, |
63 | uint32_t src_x, uint32_t src_y, | 63 | uint32_t src_x, uint32_t src_y, |
64 | uint32_t src_w, uint32_t src_h); | 64 | uint32_t src_w, uint32_t src_h, |
65 | int drm_primary_helper_disable(struct drm_plane *plane); | 65 | struct drm_modeset_acquire_ctx *ctx); |
66 | int drm_primary_helper_disable(struct drm_plane *plane, | ||
67 | struct drm_modeset_acquire_ctx *ctx); | ||
66 | void drm_primary_helper_destroy(struct drm_plane *plane); | 68 | void drm_primary_helper_destroy(struct drm_plane *plane); |
67 | extern const struct drm_plane_funcs drm_primary_helper_funcs; | 69 | extern const struct drm_plane_funcs drm_primary_helper_funcs; |
68 | 70 | ||
diff --git a/include/drm/drm_prime.h b/include/drm/drm_prime.h index d09563ecc4b7..0b2a235c4be0 100644 --- a/include/drm/drm_prime.h +++ b/include/drm/drm_prime.h | |||
@@ -57,24 +57,24 @@ struct drm_device; | |||
57 | struct drm_gem_object; | 57 | struct drm_gem_object; |
58 | struct drm_file; | 58 | struct drm_file; |
59 | 59 | ||
60 | extern struct dma_buf *drm_gem_prime_export(struct drm_device *dev, | 60 | struct dma_buf *drm_gem_prime_export(struct drm_device *dev, |
61 | struct drm_gem_object *obj, | 61 | struct drm_gem_object *obj, |
62 | int flags); | 62 | int flags); |
63 | extern int drm_gem_prime_handle_to_fd(struct drm_device *dev, | 63 | int drm_gem_prime_handle_to_fd(struct drm_device *dev, |
64 | struct drm_file *file_priv, uint32_t handle, uint32_t flags, | 64 | struct drm_file *file_priv, uint32_t handle, uint32_t flags, |
65 | int *prime_fd); | 65 | int *prime_fd); |
66 | extern struct drm_gem_object *drm_gem_prime_import(struct drm_device *dev, | 66 | struct drm_gem_object *drm_gem_prime_import(struct drm_device *dev, |
67 | struct dma_buf *dma_buf); | 67 | struct dma_buf *dma_buf); |
68 | extern int drm_gem_prime_fd_to_handle(struct drm_device *dev, | 68 | int drm_gem_prime_fd_to_handle(struct drm_device *dev, |
69 | struct drm_file *file_priv, int prime_fd, uint32_t *handle); | 69 | struct drm_file *file_priv, int prime_fd, uint32_t *handle); |
70 | struct dma_buf *drm_gem_dmabuf_export(struct drm_device *dev, | 70 | struct dma_buf *drm_gem_dmabuf_export(struct drm_device *dev, |
71 | struct dma_buf_export_info *exp_info); | 71 | struct dma_buf_export_info *exp_info); |
72 | extern void drm_gem_dmabuf_release(struct dma_buf *dma_buf); | 72 | void drm_gem_dmabuf_release(struct dma_buf *dma_buf); |
73 | 73 | ||
74 | extern int drm_prime_sg_to_page_addr_arrays(struct sg_table *sgt, struct page **pages, | 74 | int drm_prime_sg_to_page_addr_arrays(struct sg_table *sgt, struct page **pages, |
75 | dma_addr_t *addrs, int max_pages); | 75 | dma_addr_t *addrs, int max_pages); |
76 | extern struct sg_table *drm_prime_pages_to_sg(struct page **pages, unsigned int nr_pages); | 76 | struct sg_table *drm_prime_pages_to_sg(struct page **pages, unsigned int nr_pages); |
77 | extern void drm_prime_gem_destroy(struct drm_gem_object *obj, struct sg_table *sg); | 77 | void drm_prime_gem_destroy(struct drm_gem_object *obj, struct sg_table *sg); |
78 | 78 | ||
79 | 79 | ||
80 | #endif /* __DRM_PRIME_H__ */ | 80 | #endif /* __DRM_PRIME_H__ */ |
diff --git a/include/drm/drm_scdc_helper.h b/include/drm/drm_scdc_helper.h index ab6bcfbceba9..c25122bb490a 100644 --- a/include/drm/drm_scdc_helper.h +++ b/include/drm/drm_scdc_helper.h | |||
@@ -129,6 +129,8 @@ static inline int drm_scdc_writeb(struct i2c_adapter *adapter, u8 offset, | |||
129 | return drm_scdc_write(adapter, offset, &value, sizeof(value)); | 129 | return drm_scdc_write(adapter, offset, &value, sizeof(value)); |
130 | } | 130 | } |
131 | 131 | ||
132 | bool drm_scdc_get_scrambling_status(struct i2c_adapter *adapter); | ||
133 | |||
132 | /** | 134 | /** |
133 | * drm_scdc_set_scrambling - enable scrambling | 135 | * drm_scdc_set_scrambling - enable scrambling |
134 | * @adapter: I2C adapter for DDC channel | 136 | * @adapter: I2C adapter for DDC channel |
diff --git a/include/drm/drm_simple_kms_helper.h b/include/drm/drm_simple_kms_helper.h index fffbb95a0915..2d36538e4a17 100644 --- a/include/drm/drm_simple_kms_helper.h +++ b/include/drm/drm_simple_kms_helper.h | |||
@@ -72,7 +72,7 @@ struct drm_simple_display_pipe_funcs { | |||
72 | * the hardware lacks vblank support entirely. | 72 | * the hardware lacks vblank support entirely. |
73 | */ | 73 | */ |
74 | void (*update)(struct drm_simple_display_pipe *pipe, | 74 | void (*update)(struct drm_simple_display_pipe *pipe, |
75 | struct drm_plane_state *plane_state); | 75 | struct drm_plane_state *old_plane_state); |
76 | 76 | ||
77 | /** | 77 | /** |
78 | * @prepare_fb: | 78 | * @prepare_fb: |
diff --git a/include/drm/drm_sysfs.h b/include/drm/drm_sysfs.h index 1d8e033fde67..23418c1f10d1 100644 --- a/include/drm/drm_sysfs.h +++ b/include/drm/drm_sysfs.h | |||
@@ -6,7 +6,7 @@ | |||
6 | * don't want to include the full drmP.h file. | 6 | * don't want to include the full drmP.h file. |
7 | */ | 7 | */ |
8 | 8 | ||
9 | extern int drm_class_device_register(struct device *dev); | 9 | int drm_class_device_register(struct device *dev); |
10 | extern void drm_class_device_unregister(struct device *dev); | 10 | void drm_class_device_unregister(struct device *dev); |
11 | 11 | ||
12 | #endif | 12 | #endif |
diff --git a/include/drm/tinydrm/tinydrm.h b/include/drm/tinydrm/tinydrm.h index cf9ca207b8b1..00b800df4d1b 100644 --- a/include/drm/tinydrm/tinydrm.h +++ b/include/drm/tinydrm/tinydrm.h | |||
@@ -58,8 +58,7 @@ pipe_to_tinydrm(struct drm_simple_display_pipe *pipe) | |||
58 | .gem_prime_mmap = drm_gem_cma_prime_mmap, \ | 58 | .gem_prime_mmap = drm_gem_cma_prime_mmap, \ |
59 | .dumb_create = drm_gem_cma_dumb_create, \ | 59 | .dumb_create = drm_gem_cma_dumb_create, \ |
60 | .dumb_map_offset = drm_gem_cma_dumb_map_offset, \ | 60 | .dumb_map_offset = drm_gem_cma_dumb_map_offset, \ |
61 | .dumb_destroy = drm_gem_dumb_destroy, \ | 61 | .dumb_destroy = drm_gem_dumb_destroy |
62 | .fops = &tinydrm_fops | ||
63 | 62 | ||
64 | /** | 63 | /** |
65 | * TINYDRM_MODE - tinydrm display mode | 64 | * TINYDRM_MODE - tinydrm display mode |
@@ -84,7 +83,6 @@ pipe_to_tinydrm(struct drm_simple_display_pipe *pipe) | |||
84 | .type = DRM_MODE_TYPE_DRIVER, \ | 83 | .type = DRM_MODE_TYPE_DRIVER, \ |
85 | .clock = 1 /* pass validation */ | 84 | .clock = 1 /* pass validation */ |
86 | 85 | ||
87 | extern const struct file_operations tinydrm_fops; | ||
88 | void tinydrm_lastclose(struct drm_device *drm); | 86 | void tinydrm_lastclose(struct drm_device *drm); |
89 | void tinydrm_gem_cma_free_object(struct drm_gem_object *gem_obj); | 87 | void tinydrm_gem_cma_free_object(struct drm_gem_object *gem_obj); |
90 | struct drm_gem_object * | 88 | struct drm_gem_object * |
diff --git a/include/linux/pci.h b/include/linux/pci.h index eb3da1a04e6c..5948cfdc984e 100644 --- a/include/linux/pci.h +++ b/include/linux/pci.h | |||
@@ -358,6 +358,7 @@ struct pci_dev { | |||
358 | unsigned int is_virtfn:1; | 358 | unsigned int is_virtfn:1; |
359 | unsigned int reset_fn:1; | 359 | unsigned int reset_fn:1; |
360 | unsigned int is_hotplug_bridge:1; | 360 | unsigned int is_hotplug_bridge:1; |
361 | unsigned int is_thunderbolt:1; /* Thunderbolt controller */ | ||
361 | unsigned int __aer_firmware_first_valid:1; | 362 | unsigned int __aer_firmware_first_valid:1; |
362 | unsigned int __aer_firmware_first:1; | 363 | unsigned int __aer_firmware_first:1; |
363 | unsigned int broken_intx_masking:1; | 364 | unsigned int broken_intx_masking:1; |
@@ -2160,6 +2161,28 @@ static inline bool pci_ari_enabled(struct pci_bus *bus) | |||
2160 | return bus->self && bus->self->ari_enabled; | 2161 | return bus->self && bus->self->ari_enabled; |
2161 | } | 2162 | } |
2162 | 2163 | ||
2164 | /** | ||
2165 | * pci_is_thunderbolt_attached - whether device is on a Thunderbolt daisy chain | ||
2166 | * @pdev: PCI device to check | ||
2167 | * | ||
2168 | * Walk upwards from @pdev and check for each encountered bridge if it's part | ||
2169 | * of a Thunderbolt controller. Reaching the host bridge means @pdev is not | ||
2170 | * Thunderbolt-attached. (But rather soldered to the mainboard usually.) | ||
2171 | */ | ||
2172 | static inline bool pci_is_thunderbolt_attached(struct pci_dev *pdev) | ||
2173 | { | ||
2174 | struct pci_dev *parent = pdev; | ||
2175 | |||
2176 | if (pdev->is_thunderbolt) | ||
2177 | return true; | ||
2178 | |||
2179 | while ((parent = pci_upstream_bridge(parent))) | ||
2180 | if (parent->is_thunderbolt) | ||
2181 | return true; | ||
2182 | |||
2183 | return false; | ||
2184 | } | ||
2185 | |||
2163 | /* provide the legacy pci_dma_* API */ | 2186 | /* provide the legacy pci_dma_* API */ |
2164 | #include <linux/pci-dma-compat.h> | 2187 | #include <linux/pci-dma-compat.h> |
2165 | 2188 | ||