diff options
author | Daniel Vetter <daniel.vetter@ffwll.ch> | 2014-11-10 04:55:35 -0500 |
---|---|---|
committer | Daniel Vetter <daniel.vetter@ffwll.ch> | 2014-11-10 04:55:35 -0500 |
commit | eb84f976c88d72cbcbe756df38d1f19be3db77d6 (patch) | |
tree | db3ff3b5edc305a0352b69327b914ef3a92e05a5 | |
parent | 69f627f56fac212c1e49cd0d285e3f8cd264dd0c (diff) | |
parent | cc7096fb6d1dfbdac5e7e2675c046fd40646cc66 (diff) |
Merge remote-tracking branch 'airlied/drm-next' into HEAD
Backmerge drm-next so that I can keep merging patches. Specifically I
want:
- atomic stuff, yay!
- eld parsing patch from Jani.
Signed-off-by: Daniel Vetter <daniel.vetter@intel.com>
53 files changed, 3712 insertions, 445 deletions
diff --git a/Documentation/DocBook/drm.tmpl b/Documentation/DocBook/drm.tmpl index 01b8ca5f1a3d..9d9977211b23 100644 --- a/Documentation/DocBook/drm.tmpl +++ b/Documentation/DocBook/drm.tmpl | |||
@@ -996,6 +996,10 @@ int max_width, max_height;</synopsis> | |||
996 | !Edrivers/gpu/drm/drm_modes.c | 996 | !Edrivers/gpu/drm/drm_modes.c |
997 | </sect2> | 997 | </sect2> |
998 | <sect2> | 998 | <sect2> |
999 | <title>Atomic Mode Setting Function Reference</title> | ||
1000 | !Edrivers/gpu/drm/drm_atomic.c | ||
1001 | </sect2> | ||
1002 | <sect2> | ||
999 | <title>Frame Buffer Creation</title> | 1003 | <title>Frame Buffer Creation</title> |
1000 | <synopsis>struct drm_framebuffer *(*fb_create)(struct drm_device *dev, | 1004 | <synopsis>struct drm_framebuffer *(*fb_create)(struct drm_device *dev, |
1001 | struct drm_file *file_priv, | 1005 | struct drm_file *file_priv, |
@@ -1827,6 +1831,10 @@ void intel_crt_init(struct drm_device *dev) | |||
1827 | !Edrivers/gpu/drm/drm_crtc.c | 1831 | !Edrivers/gpu/drm/drm_crtc.c |
1828 | </sect2> | 1832 | </sect2> |
1829 | <sect2> | 1833 | <sect2> |
1834 | <title>KMS Data Structures</title> | ||
1835 | !Iinclude/drm/drm_crtc.h | ||
1836 | </sect2> | ||
1837 | <sect2> | ||
1830 | <title>KMS Locking</title> | 1838 | <title>KMS Locking</title> |
1831 | !Pdrivers/gpu/drm/drm_modeset_lock.c kms locking | 1839 | !Pdrivers/gpu/drm/drm_modeset_lock.c kms locking |
1832 | !Iinclude/drm/drm_modeset_lock.h | 1840 | !Iinclude/drm/drm_modeset_lock.h |
@@ -2316,8 +2324,25 @@ void intel_crt_init(struct drm_device *dev) | |||
2316 | </itemizedlist> | 2324 | </itemizedlist> |
2317 | </sect2> | 2325 | </sect2> |
2318 | <sect2> | 2326 | <sect2> |
2327 | <title>Atomic Modeset Helper Functions Reference</title> | ||
2328 | <sect3> | ||
2329 | <title>Overview</title> | ||
2330 | !Pdrivers/gpu/drm/drm_atomic_helper.c overview | ||
2331 | </sect3> | ||
2332 | <sect3> | ||
2333 | <title>Implementing Asynchronous Atomic Commit</title> | ||
2334 | !Pdrivers/gpu/drm/drm_atomic_helper.c implementing async commit | ||
2335 | </sect3> | ||
2336 | <sect3> | ||
2337 | <title>Atomic State Reset and Initialization</title> | ||
2338 | !Pdrivers/gpu/drm/drm_atomic_helper.c atomic state reset and initialization | ||
2339 | </sect3> | ||
2340 | !Edrivers/gpu/drm/drm_atomic_helper.c | ||
2341 | </sect2> | ||
2342 | <sect2> | ||
2319 | <title>Modeset Helper Functions Reference</title> | 2343 | <title>Modeset Helper Functions Reference</title> |
2320 | !Edrivers/gpu/drm/drm_crtc_helper.c | 2344 | !Edrivers/gpu/drm/drm_crtc_helper.c |
2345 | !Pdrivers/gpu/drm/drm_crtc_helper.c overview | ||
2321 | </sect2> | 2346 | </sect2> |
2322 | <sect2> | 2347 | <sect2> |
2323 | <title>Output Probing Helper Functions Reference</title> | 2348 | <title>Output Probing Helper Functions Reference</title> |
@@ -2371,7 +2396,8 @@ void intel_crt_init(struct drm_device *dev) | |||
2371 | </sect2> | 2396 | </sect2> |
2372 | <sect2> | 2397 | <sect2> |
2373 | <title id="drm-kms-planehelpers">Plane Helper Reference</title> | 2398 | <title id="drm-kms-planehelpers">Plane Helper Reference</title> |
2374 | !Edrivers/gpu/drm/drm_plane_helper.c Plane Helpers | 2399 | !Edrivers/gpu/drm/drm_plane_helper.c |
2400 | !Pdrivers/gpu/drm/drm_plane_helper.c overview | ||
2375 | </sect2> | 2401 | </sect2> |
2376 | </sect1> | 2402 | </sect1> |
2377 | 2403 | ||
@@ -2508,7 +2534,7 @@ void intel_crt_init(struct drm_device *dev) | |||
2508 | </tr> | 2534 | </tr> |
2509 | <tr> | 2535 | <tr> |
2510 | <td rowspan="21" valign="top" >DRM</td> | 2536 | <td rowspan="21" valign="top" >DRM</td> |
2511 | <td rowspan="2" valign="top" >Generic</td> | 2537 | <td rowspan="3" valign="top" >Generic</td> |
2512 | <td valign="top" >“EDID”</td> | 2538 | <td valign="top" >“EDID”</td> |
2513 | <td valign="top" >BLOB | IMMUTABLE</td> | 2539 | <td valign="top" >BLOB | IMMUTABLE</td> |
2514 | <td valign="top" >0</td> | 2540 | <td valign="top" >0</td> |
@@ -2523,6 +2549,13 @@ void intel_crt_init(struct drm_device *dev) | |||
2523 | <td valign="top" >Contains DPMS operation mode value.</td> | 2549 | <td valign="top" >Contains DPMS operation mode value.</td> |
2524 | </tr> | 2550 | </tr> |
2525 | <tr> | 2551 | <tr> |
2552 | <td valign="top" >“PATH”</td> | ||
2553 | <td valign="top" >BLOB | IMMUTABLE</td> | ||
2554 | <td valign="top" >0</td> | ||
2555 | <td valign="top" >Connector</td> | ||
2556 | <td valign="top" >Contains topology path to a connector.</td> | ||
2557 | </tr> | ||
2558 | <tr> | ||
2526 | <td rowspan="1" valign="top" >Plane</td> | 2559 | <td rowspan="1" valign="top" >Plane</td> |
2527 | <td valign="top" >“type”</td> | 2560 | <td valign="top" >“type”</td> |
2528 | <td valign="top" >ENUM | IMMUTABLE</td> | 2561 | <td valign="top" >ENUM | IMMUTABLE</td> |
diff --git a/drivers/gpu/drm/Makefile b/drivers/gpu/drm/Makefile index 9292a761ea6d..c3cf64ce2891 100644 --- a/drivers/gpu/drm/Makefile +++ b/drivers/gpu/drm/Makefile | |||
@@ -14,7 +14,7 @@ drm-y := drm_auth.o drm_bufs.o drm_cache.o \ | |||
14 | drm_info.o drm_debugfs.o drm_encoder_slave.o \ | 14 | drm_info.o drm_debugfs.o drm_encoder_slave.o \ |
15 | drm_trace_points.o drm_global.o drm_prime.o \ | 15 | drm_trace_points.o drm_global.o drm_prime.o \ |
16 | drm_rect.o drm_vma_manager.o drm_flip_work.o \ | 16 | drm_rect.o drm_vma_manager.o drm_flip_work.o \ |
17 | drm_modeset_lock.o | 17 | drm_modeset_lock.o drm_atomic.o |
18 | 18 | ||
19 | drm-$(CONFIG_COMPAT) += drm_ioc32.o | 19 | drm-$(CONFIG_COMPAT) += drm_ioc32.o |
20 | drm-$(CONFIG_DRM_GEM_CMA_HELPER) += drm_gem_cma_helper.o | 20 | drm-$(CONFIG_DRM_GEM_CMA_HELPER) += drm_gem_cma_helper.o |
@@ -23,7 +23,7 @@ drm-$(CONFIG_DRM_PANEL) += drm_panel.o | |||
23 | drm-$(CONFIG_OF) += drm_of.o | 23 | drm-$(CONFIG_OF) += drm_of.o |
24 | 24 | ||
25 | drm_kms_helper-y := drm_crtc_helper.o drm_dp_helper.o drm_probe_helper.o \ | 25 | drm_kms_helper-y := drm_crtc_helper.o drm_dp_helper.o drm_probe_helper.o \ |
26 | drm_plane_helper.o drm_dp_mst_topology.o | 26 | drm_plane_helper.o drm_dp_mst_topology.o drm_atomic_helper.o |
27 | drm_kms_helper-$(CONFIG_DRM_LOAD_EDID_FIRMWARE) += drm_edid_load.o | 27 | drm_kms_helper-$(CONFIG_DRM_LOAD_EDID_FIRMWARE) += drm_edid_load.o |
28 | drm_kms_helper-$(CONFIG_DRM_KMS_FB_HELPER) += drm_fb_helper.o | 28 | drm_kms_helper-$(CONFIG_DRM_KMS_FB_HELPER) += drm_fb_helper.o |
29 | drm_kms_helper-$(CONFIG_DRM_KMS_CMA_HELPER) += drm_fb_cma_helper.o | 29 | drm_kms_helper-$(CONFIG_DRM_KMS_CMA_HELPER) += drm_fb_cma_helper.o |
diff --git a/drivers/gpu/drm/README.drm b/drivers/gpu/drm/README.drm deleted file mode 100644 index b5b332722581..000000000000 --- a/drivers/gpu/drm/README.drm +++ /dev/null | |||
@@ -1,43 +0,0 @@ | |||
1 | ************************************************************ | ||
2 | * For the very latest on DRI development, please see: * | ||
3 | * http://dri.freedesktop.org/ * | ||
4 | ************************************************************ | ||
5 | |||
6 | The Direct Rendering Manager (drm) is a device-independent kernel-level | ||
7 | device driver that provides support for the XFree86 Direct Rendering | ||
8 | Infrastructure (DRI). | ||
9 | |||
10 | The DRM supports the Direct Rendering Infrastructure (DRI) in four major | ||
11 | ways: | ||
12 | |||
13 | 1. The DRM provides synchronized access to the graphics hardware via | ||
14 | the use of an optimized two-tiered lock. | ||
15 | |||
16 | 2. The DRM enforces the DRI security policy for access to the graphics | ||
17 | hardware by only allowing authenticated X11 clients access to | ||
18 | restricted regions of memory. | ||
19 | |||
20 | 3. The DRM provides a generic DMA engine, complete with multiple | ||
21 | queues and the ability to detect the need for an OpenGL context | ||
22 | switch. | ||
23 | |||
24 | 4. The DRM is extensible via the use of small device-specific modules | ||
25 | that rely extensively on the API exported by the DRM module. | ||
26 | |||
27 | |||
28 | Documentation on the DRI is available from: | ||
29 | http://dri.freedesktop.org/wiki/Documentation | ||
30 | http://sourceforge.net/project/showfiles.php?group_id=387 | ||
31 | http://dri.sourceforge.net/doc/ | ||
32 | |||
33 | For specific information about kernel-level support, see: | ||
34 | |||
35 | The Direct Rendering Manager, Kernel Support for the Direct Rendering | ||
36 | Infrastructure | ||
37 | http://dri.sourceforge.net/doc/drm_low_level.html | ||
38 | |||
39 | Hardware Locking for the Direct Rendering Infrastructure | ||
40 | http://dri.sourceforge.net/doc/hardware_locking_low_level.html | ||
41 | |||
42 | A Security Analysis of the Direct Rendering Infrastructure | ||
43 | http://dri.sourceforge.net/doc/security_low_level.html | ||
diff --git a/drivers/gpu/drm/armada/armada_crtc.c b/drivers/gpu/drm/armada/armada_crtc.c index 9a0cc09e6653..0b164fb1c107 100644 --- a/drivers/gpu/drm/armada/armada_crtc.c +++ b/drivers/gpu/drm/armada/armada_crtc.c | |||
@@ -12,6 +12,7 @@ | |||
12 | #include <linux/platform_device.h> | 12 | #include <linux/platform_device.h> |
13 | #include <drm/drmP.h> | 13 | #include <drm/drmP.h> |
14 | #include <drm/drm_crtc_helper.h> | 14 | #include <drm/drm_crtc_helper.h> |
15 | #include <drm/drm_plane_helper.h> | ||
15 | #include "armada_crtc.h" | 16 | #include "armada_crtc.h" |
16 | #include "armada_drm.h" | 17 | #include "armada_drm.h" |
17 | #include "armada_fb.h" | 18 | #include "armada_fb.h" |
diff --git a/drivers/gpu/drm/ast/ast_mode.c b/drivers/gpu/drm/ast/ast_mode.c index 9dc0fd5c1ea4..b7ee2634e47c 100644 --- a/drivers/gpu/drm/ast/ast_mode.c +++ b/drivers/gpu/drm/ast/ast_mode.c | |||
@@ -31,6 +31,7 @@ | |||
31 | #include <drm/drmP.h> | 31 | #include <drm/drmP.h> |
32 | #include <drm/drm_crtc.h> | 32 | #include <drm/drm_crtc.h> |
33 | #include <drm/drm_crtc_helper.h> | 33 | #include <drm/drm_crtc_helper.h> |
34 | #include <drm/drm_plane_helper.h> | ||
34 | #include "ast_drv.h" | 35 | #include "ast_drv.h" |
35 | 36 | ||
36 | #include "ast_tables.h" | 37 | #include "ast_tables.h" |
diff --git a/drivers/gpu/drm/bochs/bochs_kms.c b/drivers/gpu/drm/bochs/bochs_kms.c index 6b7efcf363d6..5ffd4895d040 100644 --- a/drivers/gpu/drm/bochs/bochs_kms.c +++ b/drivers/gpu/drm/bochs/bochs_kms.c | |||
@@ -6,6 +6,7 @@ | |||
6 | */ | 6 | */ |
7 | 7 | ||
8 | #include "bochs.h" | 8 | #include "bochs.h" |
9 | #include <drm/drm_plane_helper.h> | ||
9 | 10 | ||
10 | static int defx = 1024; | 11 | static int defx = 1024; |
11 | static int defy = 768; | 12 | static int defy = 768; |
diff --git a/drivers/gpu/drm/cirrus/cirrus_mode.c b/drivers/gpu/drm/cirrus/cirrus_mode.c index c7c5a9d91fa0..99d4a74ffeaf 100644 --- a/drivers/gpu/drm/cirrus/cirrus_mode.c +++ b/drivers/gpu/drm/cirrus/cirrus_mode.c | |||
@@ -16,6 +16,7 @@ | |||
16 | */ | 16 | */ |
17 | #include <drm/drmP.h> | 17 | #include <drm/drmP.h> |
18 | #include <drm/drm_crtc_helper.h> | 18 | #include <drm/drm_crtc_helper.h> |
19 | #include <drm/drm_plane_helper.h> | ||
19 | 20 | ||
20 | #include <video/cirrus.h> | 21 | #include <video/cirrus.h> |
21 | 22 | ||
diff --git a/drivers/gpu/drm/drm_atomic.c b/drivers/gpu/drm/drm_atomic.c new file mode 100644 index 000000000000..ed991ba66e21 --- /dev/null +++ b/drivers/gpu/drm/drm_atomic.c | |||
@@ -0,0 +1,628 @@ | |||
1 | /* | ||
2 | * Copyright (C) 2014 Red Hat | ||
3 | * Copyright (C) 2014 Intel Corp. | ||
4 | * | ||
5 | * Permission is hereby granted, free of charge, to any person obtaining a | ||
6 | * copy of this software and associated documentation files (the "Software"), | ||
7 | * to deal in the Software without restriction, including without limitation | ||
8 | * the rights to use, copy, modify, merge, publish, distribute, sublicense, | ||
9 | * and/or sell copies of the Software, and to permit persons to whom the | ||
10 | * Software is furnished to do so, subject to the following conditions: | ||
11 | * | ||
12 | * The above copyright notice and this permission notice shall be included in | ||
13 | * all copies or substantial portions of the Software. | ||
14 | * | ||
15 | * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR | ||
16 | * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, | ||
17 | * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL | ||
18 | * THE COPYRIGHT HOLDER(S) OR AUTHOR(S) BE LIABLE FOR ANY CLAIM, DAMAGES OR | ||
19 | * OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, | ||
20 | * ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR | ||
21 | * OTHER DEALINGS IN THE SOFTWARE. | ||
22 | * | ||
23 | * Authors: | ||
24 | * Rob Clark <robdclark@gmail.com> | ||
25 | * Daniel Vetter <daniel.vetter@ffwll.ch> | ||
26 | */ | ||
27 | |||
28 | |||
29 | #include <drm/drmP.h> | ||
30 | #include <drm/drm_atomic.h> | ||
31 | #include <drm/drm_plane_helper.h> | ||
32 | |||
33 | static void kfree_state(struct drm_atomic_state *state) | ||
34 | { | ||
35 | kfree(state->connectors); | ||
36 | kfree(state->connector_states); | ||
37 | kfree(state->crtcs); | ||
38 | kfree(state->crtc_states); | ||
39 | kfree(state->planes); | ||
40 | kfree(state->plane_states); | ||
41 | kfree(state); | ||
42 | } | ||
43 | |||
44 | /** | ||
45 | * drm_atomic_state_alloc - allocate atomic state | ||
46 | * @dev: DRM device | ||
47 | * | ||
48 | * This allocates an empty atomic state to track updates. | ||
49 | */ | ||
50 | struct drm_atomic_state * | ||
51 | drm_atomic_state_alloc(struct drm_device *dev) | ||
52 | { | ||
53 | struct drm_atomic_state *state; | ||
54 | |||
55 | state = kzalloc(sizeof(*state), GFP_KERNEL); | ||
56 | if (!state) | ||
57 | return NULL; | ||
58 | |||
59 | state->crtcs = kcalloc(dev->mode_config.num_crtc, | ||
60 | sizeof(*state->crtcs), GFP_KERNEL); | ||
61 | if (!state->crtcs) | ||
62 | goto fail; | ||
63 | state->crtc_states = kcalloc(dev->mode_config.num_crtc, | ||
64 | sizeof(*state->crtc_states), GFP_KERNEL); | ||
65 | if (!state->crtc_states) | ||
66 | goto fail; | ||
67 | state->planes = kcalloc(dev->mode_config.num_total_plane, | ||
68 | sizeof(*state->planes), GFP_KERNEL); | ||
69 | if (!state->planes) | ||
70 | goto fail; | ||
71 | state->plane_states = kcalloc(dev->mode_config.num_total_plane, | ||
72 | sizeof(*state->plane_states), GFP_KERNEL); | ||
73 | if (!state->plane_states) | ||
74 | goto fail; | ||
75 | state->connectors = kcalloc(dev->mode_config.num_connector, | ||
76 | sizeof(*state->connectors), | ||
77 | GFP_KERNEL); | ||
78 | if (!state->connectors) | ||
79 | goto fail; | ||
80 | state->connector_states = kcalloc(dev->mode_config.num_connector, | ||
81 | sizeof(*state->connector_states), | ||
82 | GFP_KERNEL); | ||
83 | if (!state->connector_states) | ||
84 | goto fail; | ||
85 | |||
86 | state->dev = dev; | ||
87 | |||
88 | DRM_DEBUG_KMS("Allocate atomic state %p\n", state); | ||
89 | |||
90 | return state; | ||
91 | fail: | ||
92 | kfree_state(state); | ||
93 | |||
94 | return NULL; | ||
95 | } | ||
96 | EXPORT_SYMBOL(drm_atomic_state_alloc); | ||
97 | |||
98 | /** | ||
99 | * drm_atomic_state_clear - clear state object | ||
100 | * @state: atomic state | ||
101 | * | ||
102 | * When the w/w mutex algorithm detects a deadlock we need to back off and drop | ||
103 | * all locks. So someone else could sneak in and change the current modeset | ||
104 | * configuration. Which means that all the state assembled in @state is no | ||
105 | * longer an atomic update to the current state, but to some arbitrary earlier | ||
106 | * state. Which could break assumptions the driver's ->atomic_check likely | ||
107 | * relies on. | ||
108 | * | ||
109 | * Hence we must clear all cached state and completely start over, using this | ||
110 | * function. | ||
111 | */ | ||
112 | void drm_atomic_state_clear(struct drm_atomic_state *state) | ||
113 | { | ||
114 | struct drm_device *dev = state->dev; | ||
115 | int i; | ||
116 | |||
117 | DRM_DEBUG_KMS("Clearing atomic state %p\n", state); | ||
118 | |||
119 | for (i = 0; i < dev->mode_config.num_connector; i++) { | ||
120 | struct drm_connector *connector = state->connectors[i]; | ||
121 | |||
122 | if (!connector) | ||
123 | continue; | ||
124 | |||
125 | connector->funcs->atomic_destroy_state(connector, | ||
126 | state->connector_states[i]); | ||
127 | } | ||
128 | |||
129 | for (i = 0; i < dev->mode_config.num_crtc; i++) { | ||
130 | struct drm_crtc *crtc = state->crtcs[i]; | ||
131 | |||
132 | if (!crtc) | ||
133 | continue; | ||
134 | |||
135 | crtc->funcs->atomic_destroy_state(crtc, | ||
136 | state->crtc_states[i]); | ||
137 | } | ||
138 | |||
139 | for (i = 0; i < dev->mode_config.num_total_plane; i++) { | ||
140 | struct drm_plane *plane = state->planes[i]; | ||
141 | |||
142 | if (!plane) | ||
143 | continue; | ||
144 | |||
145 | plane->funcs->atomic_destroy_state(plane, | ||
146 | state->plane_states[i]); | ||
147 | } | ||
148 | } | ||
149 | EXPORT_SYMBOL(drm_atomic_state_clear); | ||
150 | |||
151 | /** | ||
152 | * drm_atomic_state_free - free all memory for an atomic state | ||
153 | * @state: atomic state to deallocate | ||
154 | * | ||
155 | * This frees all memory associated with an atomic state, including all the | ||
156 | * per-object state for planes, crtcs and connectors. | ||
157 | */ | ||
158 | void drm_atomic_state_free(struct drm_atomic_state *state) | ||
159 | { | ||
160 | drm_atomic_state_clear(state); | ||
161 | |||
162 | DRM_DEBUG_KMS("Freeing atomic state %p\n", state); | ||
163 | |||
164 | kfree_state(state); | ||
165 | } | ||
166 | EXPORT_SYMBOL(drm_atomic_state_free); | ||
167 | |||
168 | /** | ||
169 | * drm_atomic_get_crtc_state - get crtc state | ||
170 | * @state: global atomic state object | ||
171 | * @crtc: crtc to get state object for | ||
172 | * | ||
173 | * This function returns the crtc state for the given crtc, allocating it if | ||
174 | * needed. It will also grab the relevant crtc lock to make sure that the state | ||
175 | * is consistent. | ||
176 | * | ||
177 | * Returns: | ||
178 | * | ||
179 | * Either the allocated state or the error code encoded into the pointer. When | ||
180 | * the error is EDEADLK then the w/w mutex code has detected a deadlock and the | ||
181 | * entire atomic sequence must be restarted. All other errors are fatal. | ||
182 | */ | ||
183 | struct drm_crtc_state * | ||
184 | drm_atomic_get_crtc_state(struct drm_atomic_state *state, | ||
185 | struct drm_crtc *crtc) | ||
186 | { | ||
187 | int ret, index; | ||
188 | struct drm_crtc_state *crtc_state; | ||
189 | |||
190 | index = drm_crtc_index(crtc); | ||
191 | |||
192 | if (state->crtc_states[index]) | ||
193 | return state->crtc_states[index]; | ||
194 | |||
195 | ret = drm_modeset_lock(&crtc->mutex, state->acquire_ctx); | ||
196 | if (ret) | ||
197 | return ERR_PTR(ret); | ||
198 | |||
199 | crtc_state = crtc->funcs->atomic_duplicate_state(crtc); | ||
200 | if (!crtc_state) | ||
201 | return ERR_PTR(-ENOMEM); | ||
202 | |||
203 | state->crtc_states[index] = crtc_state; | ||
204 | state->crtcs[index] = crtc; | ||
205 | crtc_state->state = state; | ||
206 | |||
207 | DRM_DEBUG_KMS("Added [CRTC:%d] %p state to %p\n", | ||
208 | crtc->base.id, crtc_state, state); | ||
209 | |||
210 | return crtc_state; | ||
211 | } | ||
212 | EXPORT_SYMBOL(drm_atomic_get_crtc_state); | ||
213 | |||
214 | /** | ||
215 | * drm_atomic_get_plane_state - get plane state | ||
216 | * @state: global atomic state object | ||
217 | * @plane: plane to get state object for | ||
218 | * | ||
219 | * This function returns the plane state for the given plane, allocating it if | ||
220 | * needed. It will also grab the relevant plane lock to make sure that the state | ||
221 | * is consistent. | ||
222 | * | ||
223 | * Returns: | ||
224 | * | ||
225 | * Either the allocated state or the error code encoded into the pointer. When | ||
226 | * the error is EDEADLK then the w/w mutex code has detected a deadlock and the | ||
227 | * entire atomic sequence must be restarted. All other errors are fatal. | ||
228 | */ | ||
229 | struct drm_plane_state * | ||
230 | drm_atomic_get_plane_state(struct drm_atomic_state *state, | ||
231 | struct drm_plane *plane) | ||
232 | { | ||
233 | int ret, index; | ||
234 | struct drm_plane_state *plane_state; | ||
235 | |||
236 | index = drm_plane_index(plane); | ||
237 | |||
238 | if (state->plane_states[index]) | ||
239 | return state->plane_states[index]; | ||
240 | |||
241 | /* | ||
242 | * TODO: We currently don't have per-plane mutexes. So instead of trying | ||
243 | * crazy tricks with deferring plane->crtc and hoping for the best just | ||
244 | * grab all crtc locks. Once we have per-plane locks we must update this | ||
245 | * to only take the plane mutex. | ||
246 | */ | ||
247 | ret = drm_modeset_lock_all_crtcs(state->dev, state->acquire_ctx); | ||
248 | if (ret) | ||
249 | return ERR_PTR(ret); | ||
250 | |||
251 | plane_state = plane->funcs->atomic_duplicate_state(plane); | ||
252 | if (!plane_state) | ||
253 | return ERR_PTR(-ENOMEM); | ||
254 | |||
255 | state->plane_states[index] = plane_state; | ||
256 | state->planes[index] = plane; | ||
257 | plane_state->state = state; | ||
258 | |||
259 | DRM_DEBUG_KMS("Added [PLANE:%d] %p state to %p\n", | ||
260 | plane->base.id, plane_state, state); | ||
261 | |||
262 | if (plane_state->crtc) { | ||
263 | struct drm_crtc_state *crtc_state; | ||
264 | |||
265 | crtc_state = drm_atomic_get_crtc_state(state, | ||
266 | plane_state->crtc); | ||
267 | if (IS_ERR(crtc_state)) | ||
268 | return ERR_CAST(crtc_state); | ||
269 | } | ||
270 | |||
271 | return plane_state; | ||
272 | } | ||
273 | EXPORT_SYMBOL(drm_atomic_get_plane_state); | ||
274 | |||
275 | /** | ||
276 | * drm_atomic_get_connector_state - get connector state | ||
277 | * @state: global atomic state object | ||
278 | * @connector: connector to get state object for | ||
279 | * | ||
280 | * This function returns the connector state for the given connector, | ||
281 | * allocating it if needed. It will also grab the relevant connector lock to | ||
282 | * make sure that the state is consistent. | ||
283 | * | ||
284 | * Returns: | ||
285 | * | ||
286 | * Either the allocated state or the error code encoded into the pointer. When | ||
287 | * the error is EDEADLK then the w/w mutex code has detected a deadlock and the | ||
288 | * entire atomic sequence must be restarted. All other errors are fatal. | ||
289 | */ | ||
290 | struct drm_connector_state * | ||
291 | drm_atomic_get_connector_state(struct drm_atomic_state *state, | ||
292 | struct drm_connector *connector) | ||
293 | { | ||
294 | int ret, index; | ||
295 | struct drm_mode_config *config = &connector->dev->mode_config; | ||
296 | struct drm_connector_state *connector_state; | ||
297 | |||
298 | index = drm_connector_index(connector); | ||
299 | |||
300 | if (state->connector_states[index]) | ||
301 | return state->connector_states[index]; | ||
302 | |||
303 | ret = drm_modeset_lock(&config->connection_mutex, state->acquire_ctx); | ||
304 | if (ret) | ||
305 | return ERR_PTR(ret); | ||
306 | |||
307 | connector_state = connector->funcs->atomic_duplicate_state(connector); | ||
308 | if (!connector_state) | ||
309 | return ERR_PTR(-ENOMEM); | ||
310 | |||
311 | state->connector_states[index] = connector_state; | ||
312 | state->connectors[index] = connector; | ||
313 | connector_state->state = state; | ||
314 | |||
315 | DRM_DEBUG_KMS("Added [CONNECTOR:%d] %p state to %p\n", | ||
316 | connector->base.id, connector_state, state); | ||
317 | |||
318 | if (connector_state->crtc) { | ||
319 | struct drm_crtc_state *crtc_state; | ||
320 | |||
321 | crtc_state = drm_atomic_get_crtc_state(state, | ||
322 | connector_state->crtc); | ||
323 | if (IS_ERR(crtc_state)) | ||
324 | return ERR_CAST(crtc_state); | ||
325 | } | ||
326 | |||
327 | return connector_state; | ||
328 | } | ||
329 | EXPORT_SYMBOL(drm_atomic_get_connector_state); | ||
330 | |||
331 | /** | ||
332 | * drm_atomic_set_crtc_for_plane - set crtc for plane | ||
333 | * @plane_state: atomic state object for the plane | ||
334 | * @crtc: crtc to use for the plane | ||
335 | * | ||
336 | * Changing the assigned crtc for a plane requires us to grab the lock and state | ||
337 | * for the new crtc, as needed. This function takes care of all these details | ||
338 | * besides updating the pointer in the state object itself. | ||
339 | * | ||
340 | * Returns: | ||
341 | * 0 on success or can fail with -EDEADLK or -ENOMEM. When the error is EDEADLK | ||
342 | * then the w/w mutex code has detected a deadlock and the entire atomic | ||
343 | * sequence must be restarted. All other errors are fatal. | ||
344 | */ | ||
345 | int | ||
346 | drm_atomic_set_crtc_for_plane(struct drm_plane_state *plane_state, | ||
347 | struct drm_crtc *crtc) | ||
348 | { | ||
349 | struct drm_crtc_state *crtc_state; | ||
350 | |||
351 | if (crtc) { | ||
352 | crtc_state = drm_atomic_get_crtc_state(plane_state->state, | ||
353 | crtc); | ||
354 | if (IS_ERR(crtc_state)) | ||
355 | return PTR_ERR(crtc_state); | ||
356 | } | ||
357 | |||
358 | plane_state->crtc = crtc; | ||
359 | |||
360 | if (crtc) | ||
361 | DRM_DEBUG_KMS("Link plane state %p to [CRTC:%d]\n", | ||
362 | plane_state, crtc->base.id); | ||
363 | else | ||
364 | DRM_DEBUG_KMS("Link plane state %p to [NOCRTC]\n", plane_state); | ||
365 | |||
366 | return 0; | ||
367 | } | ||
368 | EXPORT_SYMBOL(drm_atomic_set_crtc_for_plane); | ||
369 | |||
370 | /** | ||
371 | * drm_atomic_set_fb_for_plane - set crtc for plane | ||
372 | * @plane_state: atomic state object for the plane | ||
373 | * @fb: fb to use for the plane | ||
374 | * | ||
375 | * Changing the assigned framebuffer for a plane requires us to grab a reference | ||
376 | * to the new fb and drop the reference to the old fb, if there is one. This | ||
377 | * function takes care of all these details besides updating the pointer in the | ||
378 | * state object itself. | ||
379 | */ | ||
380 | void | ||
381 | drm_atomic_set_fb_for_plane(struct drm_plane_state *plane_state, | ||
382 | struct drm_framebuffer *fb) | ||
383 | { | ||
384 | if (plane_state->fb) | ||
385 | drm_framebuffer_unreference(plane_state->fb); | ||
386 | if (fb) | ||
387 | drm_framebuffer_reference(fb); | ||
388 | plane_state->fb = fb; | ||
389 | |||
390 | if (fb) | ||
391 | DRM_DEBUG_KMS("Set [FB:%d] for plane state %p\n", | ||
392 | fb->base.id, plane_state); | ||
393 | else | ||
394 | DRM_DEBUG_KMS("Set [NOFB] for plane state %p\n", plane_state); | ||
395 | } | ||
396 | EXPORT_SYMBOL(drm_atomic_set_fb_for_plane); | ||
397 | |||
398 | /** | ||
399 | * drm_atomic_set_crtc_for_connector - set crtc for connector | ||
400 | * @conn_state: atomic state object for the connector | ||
401 | * @crtc: crtc to use for the connector | ||
402 | * | ||
403 | * Changing the assigned crtc for a connector requires us to grab the lock and | ||
404 | * state for the new crtc, as needed. This function takes care of all these | ||
405 | * details besides updating the pointer in the state object itself. | ||
406 | * | ||
407 | * Returns: | ||
408 | * 0 on success or can fail with -EDEADLK or -ENOMEM. When the error is EDEADLK | ||
409 | * then the w/w mutex code has detected a deadlock and the entire atomic | ||
410 | * sequence must be restarted. All other errors are fatal. | ||
411 | */ | ||
412 | int | ||
413 | drm_atomic_set_crtc_for_connector(struct drm_connector_state *conn_state, | ||
414 | struct drm_crtc *crtc) | ||
415 | { | ||
416 | struct drm_crtc_state *crtc_state; | ||
417 | |||
418 | if (crtc) { | ||
419 | crtc_state = drm_atomic_get_crtc_state(conn_state->state, crtc); | ||
420 | if (IS_ERR(crtc_state)) | ||
421 | return PTR_ERR(crtc_state); | ||
422 | } | ||
423 | |||
424 | conn_state->crtc = crtc; | ||
425 | |||
426 | if (crtc) | ||
427 | DRM_DEBUG_KMS("Link connector state %p to [CRTC:%d]\n", | ||
428 | conn_state, crtc->base.id); | ||
429 | else | ||
430 | DRM_DEBUG_KMS("Link connector state %p to [NOCRTC]\n", | ||
431 | conn_state); | ||
432 | |||
433 | return 0; | ||
434 | } | ||
435 | EXPORT_SYMBOL(drm_atomic_set_crtc_for_connector); | ||
436 | |||
437 | /** | ||
438 | * drm_atomic_add_affected_connectors - add connectors for crtc | ||
439 | * @state: atomic state | ||
440 | * @crtc: DRM crtc | ||
441 | * | ||
442 | * This function walks the current configuration and adds all connectors | ||
443 | * currently using @crtc to the atomic configuration @state. Note that this | ||
444 | * function must acquire the connection mutex. This can potentially cause | ||
445 | * unneeded seralization if the update is just for the planes on one crtc. Hence | ||
446 | * drivers and helpers should only call this when really needed (e.g. when a | ||
447 | * full modeset needs to happen due to some change). | ||
448 | * | ||
449 | * Returns: | ||
450 | * 0 on success or can fail with -EDEADLK or -ENOMEM. When the error is EDEADLK | ||
451 | * then the w/w mutex code has detected a deadlock and the entire atomic | ||
452 | * sequence must be restarted. All other errors are fatal. | ||
453 | */ | ||
454 | int | ||
455 | drm_atomic_add_affected_connectors(struct drm_atomic_state *state, | ||
456 | struct drm_crtc *crtc) | ||
457 | { | ||
458 | struct drm_mode_config *config = &state->dev->mode_config; | ||
459 | struct drm_connector *connector; | ||
460 | struct drm_connector_state *conn_state; | ||
461 | int ret; | ||
462 | |||
463 | ret = drm_modeset_lock(&config->connection_mutex, state->acquire_ctx); | ||
464 | if (ret) | ||
465 | return ret; | ||
466 | |||
467 | DRM_DEBUG_KMS("Adding all current connectors for [CRTC:%d] to %p\n", | ||
468 | crtc->base.id, state); | ||
469 | |||
470 | /* | ||
471 | * Changed connectors are already in @state, so only need to look at the | ||
472 | * current configuration. | ||
473 | */ | ||
474 | list_for_each_entry(connector, &config->connector_list, head) { | ||
475 | if (connector->state->crtc != crtc) | ||
476 | continue; | ||
477 | |||
478 | conn_state = drm_atomic_get_connector_state(state, connector); | ||
479 | if (IS_ERR(conn_state)) | ||
480 | return PTR_ERR(conn_state); | ||
481 | } | ||
482 | |||
483 | return 0; | ||
484 | } | ||
485 | EXPORT_SYMBOL(drm_atomic_add_affected_connectors); | ||
486 | |||
487 | /** | ||
488 | * drm_atomic_connectors_for_crtc - count number of connected outputs | ||
489 | * @state: atomic state | ||
490 | * @crtc: DRM crtc | ||
491 | * | ||
492 | * This function counts all connectors which will be connected to @crtc | ||
493 | * according to @state. Useful to recompute the enable state for @crtc. | ||
494 | */ | ||
495 | int | ||
496 | drm_atomic_connectors_for_crtc(struct drm_atomic_state *state, | ||
497 | struct drm_crtc *crtc) | ||
498 | { | ||
499 | int nconnectors = state->dev->mode_config.num_connector; | ||
500 | int i, num_connected_connectors = 0; | ||
501 | |||
502 | for (i = 0; i < nconnectors; i++) { | ||
503 | struct drm_connector_state *conn_state; | ||
504 | |||
505 | conn_state = state->connector_states[i]; | ||
506 | |||
507 | if (conn_state && conn_state->crtc == crtc) | ||
508 | num_connected_connectors++; | ||
509 | } | ||
510 | |||
511 | DRM_DEBUG_KMS("State %p has %i connectors for [CRTC:%d]\n", | ||
512 | state, num_connected_connectors, crtc->base.id); | ||
513 | |||
514 | return num_connected_connectors; | ||
515 | } | ||
516 | EXPORT_SYMBOL(drm_atomic_connectors_for_crtc); | ||
517 | |||
518 | /** | ||
519 | * drm_atomic_legacy_backoff - locking backoff for legacy ioctls | ||
520 | * @state: atomic state | ||
521 | * | ||
522 | * This function should be used by legacy entry points which don't understand | ||
523 | * -EDEADLK semantics. For simplicity this one will grab all modeset locks after | ||
524 | * the slowpath completed. | ||
525 | */ | ||
526 | void drm_atomic_legacy_backoff(struct drm_atomic_state *state) | ||
527 | { | ||
528 | int ret; | ||
529 | |||
530 | retry: | ||
531 | drm_modeset_backoff(state->acquire_ctx); | ||
532 | |||
533 | ret = drm_modeset_lock(&state->dev->mode_config.connection_mutex, | ||
534 | state->acquire_ctx); | ||
535 | if (ret) | ||
536 | goto retry; | ||
537 | ret = drm_modeset_lock_all_crtcs(state->dev, | ||
538 | state->acquire_ctx); | ||
539 | if (ret) | ||
540 | goto retry; | ||
541 | } | ||
542 | EXPORT_SYMBOL(drm_atomic_legacy_backoff); | ||
543 | |||
544 | /** | ||
545 | * drm_atomic_check_only - check whether a given config would work | ||
546 | * @state: atomic configuration to check | ||
547 | * | ||
548 | * Note that this function can return -EDEADLK if the driver needed to acquire | ||
549 | * more locks but encountered a deadlock. The caller must then do the usual w/w | ||
550 | * backoff dance and restart. All other errors are fatal. | ||
551 | * | ||
552 | * Returns: | ||
553 | * 0 on success, negative error code on failure. | ||
554 | */ | ||
555 | int drm_atomic_check_only(struct drm_atomic_state *state) | ||
556 | { | ||
557 | struct drm_mode_config *config = &state->dev->mode_config; | ||
558 | |||
559 | DRM_DEBUG_KMS("checking %p\n", state); | ||
560 | |||
561 | if (config->funcs->atomic_check) | ||
562 | return config->funcs->atomic_check(state->dev, state); | ||
563 | else | ||
564 | return 0; | ||
565 | } | ||
566 | EXPORT_SYMBOL(drm_atomic_check_only); | ||
567 | |||
568 | /** | ||
569 | * drm_atomic_commit - commit configuration atomically | ||
570 | * @state: atomic configuration to check | ||
571 | * | ||
572 | * Note that this function can return -EDEADLK if the driver needed to acquire | ||
573 | * more locks but encountered a deadlock. The caller must then do the usual w/w | ||
574 | * backoff dance and restart. All other errors are fatal. | ||
575 | * | ||
576 | * Also note that on successful execution ownership of @state is transferred | ||
577 | * from the caller of this function to the function itself. The caller must not | ||
578 | * free or in any other way access @state. If the function fails then the caller | ||
579 | * must clean up @state itself. | ||
580 | * | ||
581 | * Returns: | ||
582 | * 0 on success, negative error code on failure. | ||
583 | */ | ||
584 | int drm_atomic_commit(struct drm_atomic_state *state) | ||
585 | { | ||
586 | struct drm_mode_config *config = &state->dev->mode_config; | ||
587 | int ret; | ||
588 | |||
589 | ret = drm_atomic_check_only(state); | ||
590 | if (ret) | ||
591 | return ret; | ||
592 | |||
593 | DRM_DEBUG_KMS("commiting %p\n", state); | ||
594 | |||
595 | return config->funcs->atomic_commit(state->dev, state, false); | ||
596 | } | ||
597 | EXPORT_SYMBOL(drm_atomic_commit); | ||
598 | |||
599 | /** | ||
600 | * drm_atomic_async_commit - atomic&async configuration commit | ||
601 | * @state: atomic configuration to check | ||
602 | * | ||
603 | * Note that this function can return -EDEADLK if the driver needed to acquire | ||
604 | * more locks but encountered a deadlock. The caller must then do the usual w/w | ||
605 | * backoff dance and restart. All other errors are fatal. | ||
606 | * | ||
607 | * Also note that on successful execution ownership of @state is transferred | ||
608 | * from the caller of this function to the function itself. The caller must not | ||
609 | * free or in any other way access @state. If the function fails then the caller | ||
610 | * must clean up @state itself. | ||
611 | * | ||
612 | * Returns: | ||
613 | * 0 on success, negative error code on failure. | ||
614 | */ | ||
615 | int drm_atomic_async_commit(struct drm_atomic_state *state) | ||
616 | { | ||
617 | struct drm_mode_config *config = &state->dev->mode_config; | ||
618 | int ret; | ||
619 | |||
620 | ret = drm_atomic_check_only(state); | ||
621 | if (ret) | ||
622 | return ret; | ||
623 | |||
624 | DRM_DEBUG_KMS("commiting %p asynchronously\n", state); | ||
625 | |||
626 | return config->funcs->atomic_commit(state->dev, state, true); | ||
627 | } | ||
628 | EXPORT_SYMBOL(drm_atomic_async_commit); | ||
diff --git a/drivers/gpu/drm/drm_atomic_helper.c b/drivers/gpu/drm/drm_atomic_helper.c new file mode 100644 index 000000000000..ca839bd9bb0d --- /dev/null +++ b/drivers/gpu/drm/drm_atomic_helper.c | |||
@@ -0,0 +1,1906 @@ | |||
1 | /* | ||
2 | * Copyright (C) 2014 Red Hat | ||
3 | * Copyright (C) 2014 Intel Corp. | ||
4 | * | ||
5 | * Permission is hereby granted, free of charge, to any person obtaining a | ||
6 | * copy of this software and associated documentation files (the "Software"), | ||
7 | * to deal in the Software without restriction, including without limitation | ||
8 | * the rights to use, copy, modify, merge, publish, distribute, sublicense, | ||
9 | * and/or sell copies of the Software, and to permit persons to whom the | ||
10 | * Software is furnished to do so, subject to the following conditions: | ||
11 | * | ||
12 | * The above copyright notice and this permission notice shall be included in | ||
13 | * all copies or substantial portions of the Software. | ||
14 | * | ||
15 | * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR | ||
16 | * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, | ||
17 | * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL | ||
18 | * THE COPYRIGHT HOLDER(S) OR AUTHOR(S) BE LIABLE FOR ANY CLAIM, DAMAGES OR | ||
19 | * OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, | ||
20 | * ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR | ||
21 | * OTHER DEALINGS IN THE SOFTWARE. | ||
22 | * | ||
23 | * Authors: | ||
24 | * Rob Clark <robdclark@gmail.com> | ||
25 | * Daniel Vetter <daniel.vetter@ffwll.ch> | ||
26 | */ | ||
27 | |||
28 | #include <drm/drmP.h> | ||
29 | #include <drm/drm_atomic.h> | ||
30 | #include <drm/drm_plane_helper.h> | ||
31 | #include <drm/drm_crtc_helper.h> | ||
32 | #include <drm/drm_atomic_helper.h> | ||
33 | #include <linux/fence.h> | ||
34 | |||
35 | /** | ||
36 | * DOC: overview | ||
37 | * | ||
38 | * This helper library provides implementations of check and commit functions on | ||
39 | * top of the CRTC modeset helper callbacks and the plane helper callbacks. It | ||
40 | * also provides convenience implementations for the atomic state handling | ||
41 | * callbacks for drivers which don't need to subclass the drm core structures to | ||
42 | * add their own additional internal state. | ||
43 | * | ||
44 | * This library also provides default implementations for the check callback in | ||
45 | * drm_atomic_helper_check and for the commit callback with | ||
46 | * drm_atomic_helper_commit. But the individual stages and callbacks are expose | ||
47 | * to allow drivers to mix and match and e.g. use the plane helpers only | ||
48 | * together with a driver private modeset implementation. | ||
49 | * | ||
50 | * This library also provides implementations for all the legacy driver | ||
51 | * interfaces on top of the atomic interface. See drm_atomic_helper_set_config, | ||
52 | * drm_atomic_helper_disable_plane, drm_atomic_helper_disable_plane and the | ||
53 | * various functions to implement set_property callbacks. New drivers must not | ||
54 | * implement these functions themselves but must use the provided helpers. | ||
55 | */ | ||
56 | static void | ||
57 | drm_atomic_helper_plane_changed(struct drm_atomic_state *state, | ||
58 | struct drm_plane_state *plane_state, | ||
59 | struct drm_plane *plane) | ||
60 | { | ||
61 | struct drm_crtc_state *crtc_state; | ||
62 | |||
63 | if (plane->state->crtc) { | ||
64 | crtc_state = state->crtc_states[drm_crtc_index(plane->crtc)]; | ||
65 | |||
66 | if (WARN_ON(!crtc_state)) | ||
67 | return; | ||
68 | |||
69 | crtc_state->planes_changed = true; | ||
70 | } | ||
71 | |||
72 | if (plane_state->crtc) { | ||
73 | crtc_state = | ||
74 | state->crtc_states[drm_crtc_index(plane_state->crtc)]; | ||
75 | |||
76 | if (WARN_ON(!crtc_state)) | ||
77 | return; | ||
78 | |||
79 | crtc_state->planes_changed = true; | ||
80 | } | ||
81 | } | ||
82 | |||
83 | static struct drm_crtc * | ||
84 | get_current_crtc_for_encoder(struct drm_device *dev, | ||
85 | struct drm_encoder *encoder) | ||
86 | { | ||
87 | struct drm_mode_config *config = &dev->mode_config; | ||
88 | struct drm_connector *connector; | ||
89 | |||
90 | WARN_ON(!drm_modeset_is_locked(&config->connection_mutex)); | ||
91 | |||
92 | list_for_each_entry(connector, &config->connector_list, head) { | ||
93 | if (connector->state->best_encoder != encoder) | ||
94 | continue; | ||
95 | |||
96 | return connector->state->crtc; | ||
97 | } | ||
98 | |||
99 | return NULL; | ||
100 | } | ||
101 | |||
102 | static int | ||
103 | steal_encoder(struct drm_atomic_state *state, | ||
104 | struct drm_encoder *encoder, | ||
105 | struct drm_crtc *encoder_crtc) | ||
106 | { | ||
107 | struct drm_mode_config *config = &state->dev->mode_config; | ||
108 | struct drm_crtc_state *crtc_state; | ||
109 | struct drm_connector *connector; | ||
110 | struct drm_connector_state *connector_state; | ||
111 | int ret; | ||
112 | |||
113 | /* | ||
114 | * We can only steal an encoder coming from a connector, which means we | ||
115 | * must already hold the connection_mutex. | ||
116 | */ | ||
117 | WARN_ON(!drm_modeset_is_locked(&config->connection_mutex)); | ||
118 | |||
119 | DRM_DEBUG_KMS("[ENCODER:%d:%s] in use on [CRTC:%d], stealing it\n", | ||
120 | encoder->base.id, encoder->name, | ||
121 | encoder_crtc->base.id); | ||
122 | |||
123 | crtc_state = drm_atomic_get_crtc_state(state, encoder_crtc); | ||
124 | if (IS_ERR(crtc_state)) | ||
125 | return PTR_ERR(crtc_state); | ||
126 | |||
127 | crtc_state->mode_changed = true; | ||
128 | |||
129 | list_for_each_entry(connector, &config->connector_list, head) { | ||
130 | if (connector->state->best_encoder != encoder) | ||
131 | continue; | ||
132 | |||
133 | DRM_DEBUG_KMS("Stealing encoder from [CONNECTOR:%d:%s]\n", | ||
134 | connector->base.id, | ||
135 | connector->name); | ||
136 | |||
137 | connector_state = drm_atomic_get_connector_state(state, | ||
138 | connector); | ||
139 | if (IS_ERR(connector_state)) | ||
140 | return PTR_ERR(connector_state); | ||
141 | |||
142 | ret = drm_atomic_set_crtc_for_connector(connector_state, NULL); | ||
143 | if (ret) | ||
144 | return ret; | ||
145 | connector_state->best_encoder = NULL; | ||
146 | } | ||
147 | |||
148 | return 0; | ||
149 | } | ||
150 | |||
151 | static int | ||
152 | update_connector_routing(struct drm_atomic_state *state, int conn_idx) | ||
153 | { | ||
154 | struct drm_connector_helper_funcs *funcs; | ||
155 | struct drm_encoder *new_encoder; | ||
156 | struct drm_crtc *encoder_crtc; | ||
157 | struct drm_connector *connector; | ||
158 | struct drm_connector_state *connector_state; | ||
159 | struct drm_crtc_state *crtc_state; | ||
160 | int idx, ret; | ||
161 | |||
162 | connector = state->connectors[conn_idx]; | ||
163 | connector_state = state->connector_states[conn_idx]; | ||
164 | |||
165 | if (!connector) | ||
166 | return 0; | ||
167 | |||
168 | DRM_DEBUG_KMS("Updating routing for [CONNECTOR:%d:%s]\n", | ||
169 | connector->base.id, | ||
170 | connector->name); | ||
171 | |||
172 | if (connector->state->crtc != connector_state->crtc) { | ||
173 | if (connector->state->crtc) { | ||
174 | idx = drm_crtc_index(connector->state->crtc); | ||
175 | |||
176 | crtc_state = state->crtc_states[idx]; | ||
177 | crtc_state->mode_changed = true; | ||
178 | } | ||
179 | |||
180 | if (connector_state->crtc) { | ||
181 | idx = drm_crtc_index(connector_state->crtc); | ||
182 | |||
183 | crtc_state = state->crtc_states[idx]; | ||
184 | crtc_state->mode_changed = true; | ||
185 | } | ||
186 | } | ||
187 | |||
188 | if (!connector_state->crtc) { | ||
189 | DRM_DEBUG_KMS("Disabling [CONNECTOR:%d:%s]\n", | ||
190 | connector->base.id, | ||
191 | connector->name); | ||
192 | |||
193 | connector_state->best_encoder = NULL; | ||
194 | |||
195 | return 0; | ||
196 | } | ||
197 | |||
198 | funcs = connector->helper_private; | ||
199 | new_encoder = funcs->best_encoder(connector); | ||
200 | |||
201 | if (!new_encoder) { | ||
202 | DRM_DEBUG_KMS("No suitable encoder found for [CONNECTOR:%d:%s]\n", | ||
203 | connector->base.id, | ||
204 | connector->name); | ||
205 | return -EINVAL; | ||
206 | } | ||
207 | |||
208 | if (new_encoder == connector_state->best_encoder) { | ||
209 | DRM_DEBUG_KMS("[CONNECTOR:%d:%s] keeps [ENCODER:%d:%s], now on [CRTC:%d]\n", | ||
210 | connector->base.id, | ||
211 | connector->name, | ||
212 | new_encoder->base.id, | ||
213 | new_encoder->name, | ||
214 | connector_state->crtc->base.id); | ||
215 | |||
216 | return 0; | ||
217 | } | ||
218 | |||
219 | encoder_crtc = get_current_crtc_for_encoder(state->dev, | ||
220 | new_encoder); | ||
221 | |||
222 | if (encoder_crtc) { | ||
223 | ret = steal_encoder(state, new_encoder, encoder_crtc); | ||
224 | if (ret) { | ||
225 | DRM_DEBUG_KMS("Encoder stealing failed for [CONNECTOR:%d:%s]\n", | ||
226 | connector->base.id, | ||
227 | connector->name); | ||
228 | return ret; | ||
229 | } | ||
230 | } | ||
231 | |||
232 | connector_state->best_encoder = new_encoder; | ||
233 | idx = drm_crtc_index(connector_state->crtc); | ||
234 | |||
235 | crtc_state = state->crtc_states[idx]; | ||
236 | crtc_state->mode_changed = true; | ||
237 | |||
238 | DRM_DEBUG_KMS("[CONNECTOR:%d:%s] using [ENCODER:%d:%s] on [CRTC:%d]\n", | ||
239 | connector->base.id, | ||
240 | connector->name, | ||
241 | new_encoder->base.id, | ||
242 | new_encoder->name, | ||
243 | connector_state->crtc->base.id); | ||
244 | |||
245 | return 0; | ||
246 | } | ||
247 | |||
248 | static int | ||
249 | mode_fixup(struct drm_atomic_state *state) | ||
250 | { | ||
251 | int ncrtcs = state->dev->mode_config.num_crtc; | ||
252 | int nconnectors = state->dev->mode_config.num_connector; | ||
253 | struct drm_crtc_state *crtc_state; | ||
254 | struct drm_connector_state *conn_state; | ||
255 | int i; | ||
256 | bool ret; | ||
257 | |||
258 | for (i = 0; i < ncrtcs; i++) { | ||
259 | crtc_state = state->crtc_states[i]; | ||
260 | |||
261 | if (!crtc_state || !crtc_state->mode_changed) | ||
262 | continue; | ||
263 | |||
264 | drm_mode_copy(&crtc_state->adjusted_mode, &crtc_state->mode); | ||
265 | } | ||
266 | |||
267 | for (i = 0; i < nconnectors; i++) { | ||
268 | struct drm_encoder_helper_funcs *funcs; | ||
269 | struct drm_encoder *encoder; | ||
270 | |||
271 | conn_state = state->connector_states[i]; | ||
272 | |||
273 | if (!conn_state) | ||
274 | continue; | ||
275 | |||
276 | WARN_ON(!!conn_state->best_encoder != !!conn_state->crtc); | ||
277 | |||
278 | if (!conn_state->crtc || !conn_state->best_encoder) | ||
279 | continue; | ||
280 | |||
281 | crtc_state = | ||
282 | state->crtc_states[drm_crtc_index(conn_state->crtc)]; | ||
283 | |||
284 | /* | ||
285 | * Each encoder has at most one connector (since we always steal | ||
286 | * it away), so we won't call ->mode_fixup twice. | ||
287 | */ | ||
288 | encoder = conn_state->best_encoder; | ||
289 | funcs = encoder->helper_private; | ||
290 | |||
291 | if (encoder->bridge && encoder->bridge->funcs->mode_fixup) { | ||
292 | ret = encoder->bridge->funcs->mode_fixup( | ||
293 | encoder->bridge, &crtc_state->mode, | ||
294 | &crtc_state->adjusted_mode); | ||
295 | if (!ret) { | ||
296 | DRM_DEBUG_KMS("Bridge fixup failed\n"); | ||
297 | return -EINVAL; | ||
298 | } | ||
299 | } | ||
300 | |||
301 | |||
302 | ret = funcs->mode_fixup(encoder, &crtc_state->mode, | ||
303 | &crtc_state->adjusted_mode); | ||
304 | if (!ret) { | ||
305 | DRM_DEBUG_KMS("[ENCODER:%d:%s] fixup failed\n", | ||
306 | encoder->base.id, encoder->name); | ||
307 | return -EINVAL; | ||
308 | } | ||
309 | } | ||
310 | |||
311 | for (i = 0; i < ncrtcs; i++) { | ||
312 | struct drm_crtc_helper_funcs *funcs; | ||
313 | struct drm_crtc *crtc; | ||
314 | |||
315 | crtc_state = state->crtc_states[i]; | ||
316 | crtc = state->crtcs[i]; | ||
317 | |||
318 | if (!crtc_state || !crtc_state->mode_changed) | ||
319 | continue; | ||
320 | |||
321 | funcs = crtc->helper_private; | ||
322 | ret = funcs->mode_fixup(crtc, &crtc_state->mode, | ||
323 | &crtc_state->adjusted_mode); | ||
324 | if (!ret) { | ||
325 | DRM_DEBUG_KMS("[CRTC:%d] fixup failed\n", | ||
326 | crtc->base.id); | ||
327 | return -EINVAL; | ||
328 | } | ||
329 | } | ||
330 | |||
331 | return 0; | ||
332 | } | ||
333 | |||
334 | static int | ||
335 | drm_atomic_helper_check_prepare(struct drm_device *dev, | ||
336 | struct drm_atomic_state *state) | ||
337 | { | ||
338 | int ncrtcs = dev->mode_config.num_crtc; | ||
339 | int nconnectors = dev->mode_config.num_connector; | ||
340 | struct drm_crtc *crtc; | ||
341 | struct drm_crtc_state *crtc_state; | ||
342 | int i, ret; | ||
343 | |||
344 | for (i = 0; i < ncrtcs; i++) { | ||
345 | crtc = state->crtcs[i]; | ||
346 | crtc_state = state->crtc_states[i]; | ||
347 | |||
348 | if (!crtc) | ||
349 | continue; | ||
350 | |||
351 | if (!drm_mode_equal(&crtc->state->mode, &crtc_state->mode)) { | ||
352 | DRM_DEBUG_KMS("[CRTC:%d] mode changed\n", | ||
353 | crtc->base.id); | ||
354 | crtc_state->mode_changed = true; | ||
355 | } | ||
356 | |||
357 | if (crtc->state->enable != crtc_state->enable) { | ||
358 | DRM_DEBUG_KMS("[CRTC:%d] enable changed\n", | ||
359 | crtc->base.id); | ||
360 | crtc_state->mode_changed = true; | ||
361 | } | ||
362 | } | ||
363 | |||
364 | for (i = 0; i < nconnectors; i++) { | ||
365 | /* | ||
366 | * This only sets crtc->mode_changed for routing changes, | ||
367 | * drivers must set crtc->mode_changed themselves when connector | ||
368 | * properties need to be updated. | ||
369 | */ | ||
370 | ret = update_connector_routing(state, i); | ||
371 | if (ret) | ||
372 | return ret; | ||
373 | } | ||
374 | |||
375 | /* | ||
376 | * After all the routing has been prepared we need to add in any | ||
377 | * connector which is itself unchanged, but who's crtc changes it's | ||
378 | * configuration. This must be done before calling mode_fixup in case a | ||
379 | * crtc only changed its mode but has the same set of connectors. | ||
380 | */ | ||
381 | for (i = 0; i < ncrtcs; i++) { | ||
382 | int num_connectors; | ||
383 | |||
384 | crtc = state->crtcs[i]; | ||
385 | crtc_state = state->crtc_states[i]; | ||
386 | |||
387 | if (!crtc || !crtc_state->mode_changed) | ||
388 | continue; | ||
389 | |||
390 | DRM_DEBUG_KMS("[CRTC:%d] needs full modeset, enable: %c\n", | ||
391 | crtc->base.id, | ||
392 | crtc_state->enable ? 'y' : 'n'); | ||
393 | |||
394 | ret = drm_atomic_add_affected_connectors(state, crtc); | ||
395 | if (ret != 0) | ||
396 | return ret; | ||
397 | |||
398 | num_connectors = drm_atomic_connectors_for_crtc(state, | ||
399 | crtc); | ||
400 | |||
401 | if (crtc_state->enable != !!num_connectors) { | ||
402 | DRM_DEBUG_KMS("[CRTC:%d] enabled/connectors mismatch\n", | ||
403 | crtc->base.id); | ||
404 | |||
405 | return -EINVAL; | ||
406 | } | ||
407 | } | ||
408 | |||
409 | return mode_fixup(state); | ||
410 | } | ||
411 | |||
412 | /** | ||
413 | * drm_atomic_helper_check - validate state object | ||
414 | * @dev: DRM device | ||
415 | * @state: the driver state object | ||
416 | * | ||
417 | * Check the state object to see if the requested state is physically possible. | ||
418 | * Only crtcs and planes have check callbacks, so for any additional (global) | ||
419 | * checking that a driver needs it can simply wrap that around this function. | ||
420 | * Drivers without such needs can directly use this as their ->atomic_check() | ||
421 | * callback. | ||
422 | * | ||
423 | * RETURNS | ||
424 | * Zero for success or -errno | ||
425 | */ | ||
426 | int drm_atomic_helper_check(struct drm_device *dev, | ||
427 | struct drm_atomic_state *state) | ||
428 | { | ||
429 | int nplanes = dev->mode_config.num_total_plane; | ||
430 | int ncrtcs = dev->mode_config.num_crtc; | ||
431 | int i, ret = 0; | ||
432 | |||
433 | ret = drm_atomic_helper_check_prepare(dev, state); | ||
434 | if (ret) | ||
435 | return ret; | ||
436 | |||
437 | for (i = 0; i < nplanes; i++) { | ||
438 | struct drm_plane_helper_funcs *funcs; | ||
439 | struct drm_plane *plane = state->planes[i]; | ||
440 | struct drm_plane_state *plane_state = state->plane_states[i]; | ||
441 | |||
442 | if (!plane) | ||
443 | continue; | ||
444 | |||
445 | funcs = plane->helper_private; | ||
446 | |||
447 | drm_atomic_helper_plane_changed(state, plane_state, plane); | ||
448 | |||
449 | if (!funcs || !funcs->atomic_check) | ||
450 | continue; | ||
451 | |||
452 | ret = funcs->atomic_check(plane, plane_state); | ||
453 | if (ret) { | ||
454 | DRM_DEBUG_KMS("[PLANE:%d] atomic check failed\n", | ||
455 | plane->base.id); | ||
456 | return ret; | ||
457 | } | ||
458 | } | ||
459 | |||
460 | for (i = 0; i < ncrtcs; i++) { | ||
461 | struct drm_crtc_helper_funcs *funcs; | ||
462 | struct drm_crtc *crtc = state->crtcs[i]; | ||
463 | |||
464 | if (!crtc) | ||
465 | continue; | ||
466 | |||
467 | funcs = crtc->helper_private; | ||
468 | |||
469 | if (!funcs || !funcs->atomic_check) | ||
470 | continue; | ||
471 | |||
472 | ret = funcs->atomic_check(crtc, state->crtc_states[i]); | ||
473 | if (ret) { | ||
474 | DRM_DEBUG_KMS("[CRTC:%d] atomic check failed\n", | ||
475 | crtc->base.id); | ||
476 | return ret; | ||
477 | } | ||
478 | } | ||
479 | |||
480 | return ret; | ||
481 | } | ||
482 | EXPORT_SYMBOL(drm_atomic_helper_check); | ||
483 | |||
484 | static void | ||
485 | disable_outputs(struct drm_device *dev, struct drm_atomic_state *old_state) | ||
486 | { | ||
487 | int ncrtcs = old_state->dev->mode_config.num_crtc; | ||
488 | int nconnectors = old_state->dev->mode_config.num_connector; | ||
489 | int i; | ||
490 | |||
491 | for (i = 0; i < nconnectors; i++) { | ||
492 | struct drm_connector_state *old_conn_state; | ||
493 | struct drm_connector *connector; | ||
494 | struct drm_encoder_helper_funcs *funcs; | ||
495 | struct drm_encoder *encoder; | ||
496 | |||
497 | old_conn_state = old_state->connector_states[i]; | ||
498 | connector = old_state->connectors[i]; | ||
499 | |||
500 | /* Shut down everything that's in the changeset and currently | ||
501 | * still on. So need to check the old, saved state. */ | ||
502 | if (!old_conn_state || !old_conn_state->crtc) | ||
503 | continue; | ||
504 | |||
505 | encoder = connector->state->best_encoder; | ||
506 | |||
507 | if (!encoder) | ||
508 | continue; | ||
509 | |||
510 | funcs = encoder->helper_private; | ||
511 | |||
512 | /* | ||
513 | * Each encoder has at most one connector (since we always steal | ||
514 | * it away), so we won't call call disable hooks twice. | ||
515 | */ | ||
516 | if (encoder->bridge) | ||
517 | encoder->bridge->funcs->disable(encoder->bridge); | ||
518 | |||
519 | /* Right function depends upon target state. */ | ||
520 | if (connector->state->crtc) | ||
521 | funcs->prepare(encoder); | ||
522 | else if (funcs->disable) | ||
523 | funcs->disable(encoder); | ||
524 | else | ||
525 | funcs->dpms(encoder, DRM_MODE_DPMS_OFF); | ||
526 | |||
527 | if (encoder->bridge) | ||
528 | encoder->bridge->funcs->post_disable(encoder->bridge); | ||
529 | } | ||
530 | |||
531 | for (i = 0; i < ncrtcs; i++) { | ||
532 | struct drm_crtc_helper_funcs *funcs; | ||
533 | struct drm_crtc *crtc; | ||
534 | |||
535 | crtc = old_state->crtcs[i]; | ||
536 | |||
537 | /* Shut down everything that needs a full modeset. */ | ||
538 | if (!crtc || !crtc->state->mode_changed) | ||
539 | continue; | ||
540 | |||
541 | funcs = crtc->helper_private; | ||
542 | |||
543 | /* Right function depends upon target state. */ | ||
544 | if (crtc->state->enable) | ||
545 | funcs->prepare(crtc); | ||
546 | else if (funcs->disable) | ||
547 | funcs->disable(crtc); | ||
548 | else | ||
549 | funcs->dpms(crtc, DRM_MODE_DPMS_OFF); | ||
550 | } | ||
551 | } | ||
552 | |||
553 | static void | ||
554 | set_routing_links(struct drm_device *dev, struct drm_atomic_state *old_state) | ||
555 | { | ||
556 | int nconnectors = dev->mode_config.num_connector; | ||
557 | int ncrtcs = old_state->dev->mode_config.num_crtc; | ||
558 | int i; | ||
559 | |||
560 | /* clear out existing links */ | ||
561 | for (i = 0; i < nconnectors; i++) { | ||
562 | struct drm_connector *connector; | ||
563 | |||
564 | connector = old_state->connectors[i]; | ||
565 | |||
566 | if (!connector || !connector->encoder) | ||
567 | continue; | ||
568 | |||
569 | WARN_ON(!connector->encoder->crtc); | ||
570 | |||
571 | connector->encoder->crtc = NULL; | ||
572 | connector->encoder = NULL; | ||
573 | } | ||
574 | |||
575 | /* set new links */ | ||
576 | for (i = 0; i < nconnectors; i++) { | ||
577 | struct drm_connector *connector; | ||
578 | |||
579 | connector = old_state->connectors[i]; | ||
580 | |||
581 | if (!connector || !connector->state->crtc) | ||
582 | continue; | ||
583 | |||
584 | if (WARN_ON(!connector->state->best_encoder)) | ||
585 | continue; | ||
586 | |||
587 | connector->encoder = connector->state->best_encoder; | ||
588 | connector->encoder->crtc = connector->state->crtc; | ||
589 | } | ||
590 | |||
591 | /* set legacy state in the crtc structure */ | ||
592 | for (i = 0; i < ncrtcs; i++) { | ||
593 | struct drm_crtc *crtc; | ||
594 | |||
595 | crtc = old_state->crtcs[i]; | ||
596 | |||
597 | if (!crtc) | ||
598 | continue; | ||
599 | |||
600 | crtc->mode = crtc->state->mode; | ||
601 | crtc->enabled = crtc->state->enable; | ||
602 | crtc->x = crtc->primary->state->src_x >> 16; | ||
603 | crtc->y = crtc->primary->state->src_y >> 16; | ||
604 | } | ||
605 | } | ||
606 | |||
607 | static void | ||
608 | crtc_set_mode(struct drm_device *dev, struct drm_atomic_state *old_state) | ||
609 | { | ||
610 | int ncrtcs = old_state->dev->mode_config.num_crtc; | ||
611 | int nconnectors = old_state->dev->mode_config.num_connector; | ||
612 | int i; | ||
613 | |||
614 | for (i = 0; i < ncrtcs; i++) { | ||
615 | struct drm_crtc_helper_funcs *funcs; | ||
616 | struct drm_crtc *crtc; | ||
617 | |||
618 | crtc = old_state->crtcs[i]; | ||
619 | |||
620 | if (!crtc || !crtc->state->mode_changed) | ||
621 | continue; | ||
622 | |||
623 | funcs = crtc->helper_private; | ||
624 | |||
625 | if (crtc->state->enable) | ||
626 | funcs->mode_set_nofb(crtc); | ||
627 | } | ||
628 | |||
629 | for (i = 0; i < nconnectors; i++) { | ||
630 | struct drm_connector *connector; | ||
631 | struct drm_crtc_state *new_crtc_state; | ||
632 | struct drm_encoder_helper_funcs *funcs; | ||
633 | struct drm_encoder *encoder; | ||
634 | struct drm_display_mode *mode, *adjusted_mode; | ||
635 | |||
636 | connector = old_state->connectors[i]; | ||
637 | |||
638 | if (!connector || !connector->state->best_encoder) | ||
639 | continue; | ||
640 | |||
641 | encoder = connector->state->best_encoder; | ||
642 | funcs = encoder->helper_private; | ||
643 | new_crtc_state = connector->state->crtc->state; | ||
644 | mode = &new_crtc_state->mode; | ||
645 | adjusted_mode = &new_crtc_state->adjusted_mode; | ||
646 | |||
647 | /* | ||
648 | * Each encoder has at most one connector (since we always steal | ||
649 | * it away), so we won't call call mode_set hooks twice. | ||
650 | */ | ||
651 | funcs->mode_set(encoder, mode, adjusted_mode); | ||
652 | |||
653 | if (encoder->bridge && encoder->bridge->funcs->mode_set) | ||
654 | encoder->bridge->funcs->mode_set(encoder->bridge, | ||
655 | mode, adjusted_mode); | ||
656 | } | ||
657 | } | ||
658 | |||
659 | /** | ||
660 | * drm_atomic_helper_commit_pre_planes - modeset commit before plane updates | ||
661 | * @dev: DRM device | ||
662 | * @state: atomic state | ||
663 | * | ||
664 | * This function commits the modeset changes that need to be committed before | ||
665 | * updating planes. It shuts down all the outputs that need to be shut down and | ||
666 | * prepares them (if required) with the new mode. | ||
667 | */ | ||
668 | void drm_atomic_helper_commit_pre_planes(struct drm_device *dev, | ||
669 | struct drm_atomic_state *state) | ||
670 | { | ||
671 | disable_outputs(dev, state); | ||
672 | set_routing_links(dev, state); | ||
673 | crtc_set_mode(dev, state); | ||
674 | } | ||
675 | EXPORT_SYMBOL(drm_atomic_helper_commit_pre_planes); | ||
676 | |||
677 | /** | ||
678 | * drm_atomic_helper_commit_post_planes - modeset commit after plane updates | ||
679 | * @dev: DRM device | ||
680 | * @old_state: atomic state object with old state structures | ||
681 | * | ||
682 | * This function commits the modeset changes that need to be committed after | ||
683 | * updating planes: It enables all the outputs with the new configuration which | ||
684 | * had to be turned off for the update. | ||
685 | */ | ||
686 | void drm_atomic_helper_commit_post_planes(struct drm_device *dev, | ||
687 | struct drm_atomic_state *old_state) | ||
688 | { | ||
689 | int ncrtcs = old_state->dev->mode_config.num_crtc; | ||
690 | int nconnectors = old_state->dev->mode_config.num_connector; | ||
691 | int i; | ||
692 | |||
693 | for (i = 0; i < ncrtcs; i++) { | ||
694 | struct drm_crtc_helper_funcs *funcs; | ||
695 | struct drm_crtc *crtc; | ||
696 | |||
697 | crtc = old_state->crtcs[i]; | ||
698 | |||
699 | /* Need to filter out CRTCs where only planes change. */ | ||
700 | if (!crtc || !crtc->state->mode_changed) | ||
701 | continue; | ||
702 | |||
703 | funcs = crtc->helper_private; | ||
704 | |||
705 | if (crtc->state->enable) | ||
706 | funcs->commit(crtc); | ||
707 | } | ||
708 | |||
709 | for (i = 0; i < nconnectors; i++) { | ||
710 | struct drm_connector *connector; | ||
711 | struct drm_encoder_helper_funcs *funcs; | ||
712 | struct drm_encoder *encoder; | ||
713 | |||
714 | connector = old_state->connectors[i]; | ||
715 | |||
716 | if (!connector || !connector->state->best_encoder) | ||
717 | continue; | ||
718 | |||
719 | encoder = connector->state->best_encoder; | ||
720 | funcs = encoder->helper_private; | ||
721 | |||
722 | /* | ||
723 | * Each encoder has at most one connector (since we always steal | ||
724 | * it away), so we won't call call enable hooks twice. | ||
725 | */ | ||
726 | if (encoder->bridge) | ||
727 | encoder->bridge->funcs->pre_enable(encoder->bridge); | ||
728 | |||
729 | funcs->commit(encoder); | ||
730 | |||
731 | if (encoder->bridge) | ||
732 | encoder->bridge->funcs->enable(encoder->bridge); | ||
733 | } | ||
734 | } | ||
735 | EXPORT_SYMBOL(drm_atomic_helper_commit_post_planes); | ||
736 | |||
737 | static void wait_for_fences(struct drm_device *dev, | ||
738 | struct drm_atomic_state *state) | ||
739 | { | ||
740 | int nplanes = dev->mode_config.num_total_plane; | ||
741 | int i; | ||
742 | |||
743 | for (i = 0; i < nplanes; i++) { | ||
744 | struct drm_plane *plane = state->planes[i]; | ||
745 | |||
746 | if (!plane || !plane->state->fence) | ||
747 | continue; | ||
748 | |||
749 | WARN_ON(!plane->state->fb); | ||
750 | |||
751 | fence_wait(plane->state->fence, false); | ||
752 | fence_put(plane->state->fence); | ||
753 | plane->state->fence = NULL; | ||
754 | } | ||
755 | } | ||
756 | |||
757 | static void | ||
758 | wait_for_vblanks(struct drm_device *dev, struct drm_atomic_state *old_state) | ||
759 | { | ||
760 | struct drm_crtc *crtc; | ||
761 | struct drm_crtc_state *old_crtc_state; | ||
762 | int ncrtcs = old_state->dev->mode_config.num_crtc; | ||
763 | int i, ret; | ||
764 | |||
765 | for (i = 0; i < ncrtcs; i++) { | ||
766 | crtc = old_state->crtcs[i]; | ||
767 | old_crtc_state = old_state->crtc_states[i]; | ||
768 | |||
769 | if (!crtc) | ||
770 | continue; | ||
771 | |||
772 | /* No one cares about the old state, so abuse it for tracking | ||
773 | * and store whether we hold a vblank reference (and should do a | ||
774 | * vblank wait) in the ->enable boolean. */ | ||
775 | old_crtc_state->enable = false; | ||
776 | |||
777 | if (!crtc->state->enable) | ||
778 | continue; | ||
779 | |||
780 | ret = drm_crtc_vblank_get(crtc); | ||
781 | if (ret != 0) | ||
782 | continue; | ||
783 | |||
784 | old_crtc_state->enable = true; | ||
785 | old_crtc_state->last_vblank_count = drm_vblank_count(dev, i); | ||
786 | } | ||
787 | |||
788 | for (i = 0; i < ncrtcs; i++) { | ||
789 | crtc = old_state->crtcs[i]; | ||
790 | old_crtc_state = old_state->crtc_states[i]; | ||
791 | |||
792 | if (!crtc || !old_crtc_state->enable) | ||
793 | continue; | ||
794 | |||
795 | ret = wait_event_timeout(dev->vblank[i].queue, | ||
796 | old_crtc_state->last_vblank_count != | ||
797 | drm_vblank_count(dev, i), | ||
798 | msecs_to_jiffies(50)); | ||
799 | |||
800 | drm_crtc_vblank_put(crtc); | ||
801 | } | ||
802 | } | ||
803 | |||
804 | /** | ||
805 | * drm_atomic_helper_commit - commit validated state object | ||
806 | * @dev: DRM device | ||
807 | * @state: the driver state object | ||
808 | * @async: asynchronous commit | ||
809 | * | ||
810 | * This function commits a with drm_atomic_helper_check() pre-validated state | ||
811 | * object. This can still fail when e.g. the framebuffer reservation fails. For | ||
812 | * now this doesn't implement asynchronous commits. | ||
813 | * | ||
814 | * RETURNS | ||
815 | * Zero for success or -errno. | ||
816 | */ | ||
817 | int drm_atomic_helper_commit(struct drm_device *dev, | ||
818 | struct drm_atomic_state *state, | ||
819 | bool async) | ||
820 | { | ||
821 | int ret; | ||
822 | |||
823 | if (async) | ||
824 | return -EBUSY; | ||
825 | |||
826 | ret = drm_atomic_helper_prepare_planes(dev, state); | ||
827 | if (ret) | ||
828 | return ret; | ||
829 | |||
830 | /* | ||
831 | * This is the point of no return - everything below never fails except | ||
832 | * when the hw goes bonghits. Which means we can commit the new state on | ||
833 | * the software side now. | ||
834 | */ | ||
835 | |||
836 | drm_atomic_helper_swap_state(dev, state); | ||
837 | |||
838 | /* | ||
839 | * Everything below can be run asynchronously without the need to grab | ||
840 | * any modeset locks at all under one conditions: It must be guaranteed | ||
841 | * that the asynchronous work has either been cancelled (if the driver | ||
842 | * supports it, which at least requires that the framebuffers get | ||
843 | * cleaned up with drm_atomic_helper_cleanup_planes()) or completed | ||
844 | * before the new state gets committed on the software side with | ||
845 | * drm_atomic_helper_swap_state(). | ||
846 | * | ||
847 | * This scheme allows new atomic state updates to be prepared and | ||
848 | * checked in parallel to the asynchronous completion of the previous | ||
849 | * update. Which is important since compositors need to figure out the | ||
850 | * composition of the next frame right after having submitted the | ||
851 | * current layout. | ||
852 | */ | ||
853 | |||
854 | wait_for_fences(dev, state); | ||
855 | |||
856 | drm_atomic_helper_commit_pre_planes(dev, state); | ||
857 | |||
858 | drm_atomic_helper_commit_planes(dev, state); | ||
859 | |||
860 | drm_atomic_helper_commit_post_planes(dev, state); | ||
861 | |||
862 | wait_for_vblanks(dev, state); | ||
863 | |||
864 | drm_atomic_helper_cleanup_planes(dev, state); | ||
865 | |||
866 | drm_atomic_state_free(state); | ||
867 | |||
868 | return 0; | ||
869 | } | ||
870 | EXPORT_SYMBOL(drm_atomic_helper_commit); | ||
871 | |||
872 | /** | ||
873 | * DOC: implementing async commit | ||
874 | * | ||
875 | * For now the atomic helpers don't support async commit directly. If there is | ||
876 | * real need it could be added though, using the dma-buf fence infrastructure | ||
877 | * for generic synchronization with outstanding rendering. | ||
878 | * | ||
879 | * For now drivers have to implement async commit themselves, with the following | ||
880 | * sequence being the recommended one: | ||
881 | * | ||
882 | * 1. Run drm_atomic_helper_prepare_planes() first. This is the only function | ||
883 | * which commit needs to call which can fail, so we want to run it first and | ||
884 | * synchronously. | ||
885 | * | ||
886 | * 2. Synchronize with any outstanding asynchronous commit worker threads which | ||
887 | * might be affected the new state update. This can be done by either cancelling | ||
888 | * or flushing the work items, depending upon whether the driver can deal with | ||
889 | * cancelled updates. Note that it is important to ensure that the framebuffer | ||
890 | * cleanup is still done when cancelling. | ||
891 | * | ||
892 | * For sufficient parallelism it is recommended to have a work item per crtc | ||
893 | * (for updates which don't touch global state) and a global one. Then we only | ||
894 | * need to synchronize with the crtc work items for changed crtcs and the global | ||
895 | * work item, which allows nice concurrent updates on disjoint sets of crtcs. | ||
896 | * | ||
897 | * 3. The software state is updated synchronously with | ||
898 | * drm_atomic_helper_swap_state. Doing this under the protection of all modeset | ||
899 | * locks means concurrent callers never see inconsistent state. And doing this | ||
900 | * while it's guaranteed that no relevant async worker runs means that async | ||
901 | * workers do not need grab any locks. Actually they must not grab locks, for | ||
902 | * otherwise the work flushing will deadlock. | ||
903 | * | ||
904 | * 4. Schedule a work item to do all subsequent steps, using the split-out | ||
905 | * commit helpers: a) pre-plane commit b) plane commit c) post-plane commit and | ||
906 | * then cleaning up the framebuffers after the old framebuffer is no longer | ||
907 | * being displayed. | ||
908 | */ | ||
909 | |||
910 | /** | ||
911 | * drm_atomic_helper_prepare_planes - prepare plane resources after commit | ||
912 | * @dev: DRM device | ||
913 | * @state: atomic state object with old state structures | ||
914 | * | ||
915 | * This function prepares plane state, specifically framebuffers, for the new | ||
916 | * configuration. If any failure is encountered this function will call | ||
917 | * ->cleanup_fb on any already successfully prepared framebuffer. | ||
918 | * | ||
919 | * Returns: | ||
920 | * 0 on success, negative error code on failure. | ||
921 | */ | ||
922 | int drm_atomic_helper_prepare_planes(struct drm_device *dev, | ||
923 | struct drm_atomic_state *state) | ||
924 | { | ||
925 | int nplanes = dev->mode_config.num_total_plane; | ||
926 | int ret, i; | ||
927 | |||
928 | for (i = 0; i < nplanes; i++) { | ||
929 | struct drm_plane_helper_funcs *funcs; | ||
930 | struct drm_plane *plane = state->planes[i]; | ||
931 | struct drm_framebuffer *fb; | ||
932 | |||
933 | if (!plane) | ||
934 | continue; | ||
935 | |||
936 | funcs = plane->helper_private; | ||
937 | |||
938 | fb = state->plane_states[i]->fb; | ||
939 | |||
940 | if (fb && funcs->prepare_fb) { | ||
941 | ret = funcs->prepare_fb(plane, fb); | ||
942 | if (ret) | ||
943 | goto fail; | ||
944 | } | ||
945 | } | ||
946 | |||
947 | return 0; | ||
948 | |||
949 | fail: | ||
950 | for (i--; i >= 0; i--) { | ||
951 | struct drm_plane_helper_funcs *funcs; | ||
952 | struct drm_plane *plane = state->planes[i]; | ||
953 | struct drm_framebuffer *fb; | ||
954 | |||
955 | if (!plane) | ||
956 | continue; | ||
957 | |||
958 | funcs = plane->helper_private; | ||
959 | |||
960 | fb = state->plane_states[i]->fb; | ||
961 | |||
962 | if (fb && funcs->cleanup_fb) | ||
963 | funcs->cleanup_fb(plane, fb); | ||
964 | |||
965 | } | ||
966 | |||
967 | return ret; | ||
968 | } | ||
969 | EXPORT_SYMBOL(drm_atomic_helper_prepare_planes); | ||
970 | |||
971 | /** | ||
972 | * drm_atomic_helper_commit_planes - commit plane state | ||
973 | * @dev: DRM device | ||
974 | * @state: atomic state | ||
975 | * | ||
976 | * This function commits the new plane state using the plane and atomic helper | ||
977 | * functions for planes and crtcs. It assumes that the atomic state has already | ||
978 | * been pushed into the relevant object state pointers, since this step can no | ||
979 | * longer fail. | ||
980 | * | ||
981 | * It still requires the global state object @state to know which planes and | ||
982 | * crtcs need to be updated though. | ||
983 | */ | ||
984 | void drm_atomic_helper_commit_planes(struct drm_device *dev, | ||
985 | struct drm_atomic_state *state) | ||
986 | { | ||
987 | int nplanes = dev->mode_config.num_total_plane; | ||
988 | int ncrtcs = dev->mode_config.num_crtc; | ||
989 | int i; | ||
990 | |||
991 | for (i = 0; i < ncrtcs; i++) { | ||
992 | struct drm_crtc_helper_funcs *funcs; | ||
993 | struct drm_crtc *crtc = state->crtcs[i]; | ||
994 | |||
995 | if (!crtc) | ||
996 | continue; | ||
997 | |||
998 | funcs = crtc->helper_private; | ||
999 | |||
1000 | if (!funcs || !funcs->atomic_begin) | ||
1001 | continue; | ||
1002 | |||
1003 | funcs->atomic_begin(crtc); | ||
1004 | } | ||
1005 | |||
1006 | for (i = 0; i < nplanes; i++) { | ||
1007 | struct drm_plane_helper_funcs *funcs; | ||
1008 | struct drm_plane *plane = state->planes[i]; | ||
1009 | |||
1010 | if (!plane) | ||
1011 | continue; | ||
1012 | |||
1013 | funcs = plane->helper_private; | ||
1014 | |||
1015 | if (!funcs || !funcs->atomic_update) | ||
1016 | continue; | ||
1017 | |||
1018 | funcs->atomic_update(plane); | ||
1019 | } | ||
1020 | |||
1021 | for (i = 0; i < ncrtcs; i++) { | ||
1022 | struct drm_crtc_helper_funcs *funcs; | ||
1023 | struct drm_crtc *crtc = state->crtcs[i]; | ||
1024 | |||
1025 | if (!crtc) | ||
1026 | continue; | ||
1027 | |||
1028 | funcs = crtc->helper_private; | ||
1029 | |||
1030 | if (!funcs || !funcs->atomic_flush) | ||
1031 | continue; | ||
1032 | |||
1033 | funcs->atomic_flush(crtc); | ||
1034 | } | ||
1035 | } | ||
1036 | EXPORT_SYMBOL(drm_atomic_helper_commit_planes); | ||
1037 | |||
1038 | /** | ||
1039 | * drm_atomic_helper_cleanup_planes - cleanup plane resources after commit | ||
1040 | * @dev: DRM device | ||
1041 | * @old_state: atomic state object with old state structures | ||
1042 | * | ||
1043 | * This function cleans up plane state, specifically framebuffers, from the old | ||
1044 | * configuration. Hence the old configuration must be perserved in @old_state to | ||
1045 | * be able to call this function. | ||
1046 | * | ||
1047 | * This function must also be called on the new state when the atomic update | ||
1048 | * fails at any point after calling drm_atomic_helper_prepare_planes(). | ||
1049 | */ | ||
1050 | void drm_atomic_helper_cleanup_planes(struct drm_device *dev, | ||
1051 | struct drm_atomic_state *old_state) | ||
1052 | { | ||
1053 | int nplanes = dev->mode_config.num_total_plane; | ||
1054 | int i; | ||
1055 | |||
1056 | for (i = 0; i < nplanes; i++) { | ||
1057 | struct drm_plane_helper_funcs *funcs; | ||
1058 | struct drm_plane *plane = old_state->planes[i]; | ||
1059 | struct drm_framebuffer *old_fb; | ||
1060 | |||
1061 | if (!plane) | ||
1062 | continue; | ||
1063 | |||
1064 | funcs = plane->helper_private; | ||
1065 | |||
1066 | old_fb = old_state->plane_states[i]->fb; | ||
1067 | |||
1068 | if (old_fb && funcs->cleanup_fb) | ||
1069 | funcs->cleanup_fb(plane, old_fb); | ||
1070 | } | ||
1071 | } | ||
1072 | EXPORT_SYMBOL(drm_atomic_helper_cleanup_planes); | ||
1073 | |||
1074 | /** | ||
1075 | * drm_atomic_helper_swap_state - store atomic state into current sw state | ||
1076 | * @dev: DRM device | ||
1077 | * @state: atomic state | ||
1078 | * | ||
1079 | * This function stores the atomic state into the current state pointers in all | ||
1080 | * driver objects. It should be called after all failing steps have been done | ||
1081 | * and succeeded, but before the actual hardware state is committed. | ||
1082 | * | ||
1083 | * For cleanup and error recovery the current state for all changed objects will | ||
1084 | * be swaped into @state. | ||
1085 | * | ||
1086 | * With that sequence it fits perfectly into the plane prepare/cleanup sequence: | ||
1087 | * | ||
1088 | * 1. Call drm_atomic_helper_prepare_planes() with the staged atomic state. | ||
1089 | * | ||
1090 | * 2. Do any other steps that might fail. | ||
1091 | * | ||
1092 | * 3. Put the staged state into the current state pointers with this function. | ||
1093 | * | ||
1094 | * 4. Actually commit the hardware state. | ||
1095 | * | ||
1096 | * 5. Call drm_atomic_helper_cleanup_planes with @state, which since step 3 | ||
1097 | * contains the old state. Also do any other cleanup required with that state. | ||
1098 | */ | ||
1099 | void drm_atomic_helper_swap_state(struct drm_device *dev, | ||
1100 | struct drm_atomic_state *state) | ||
1101 | { | ||
1102 | int i; | ||
1103 | |||
1104 | for (i = 0; i < dev->mode_config.num_connector; i++) { | ||
1105 | struct drm_connector *connector = state->connectors[i]; | ||
1106 | |||
1107 | if (!connector) | ||
1108 | continue; | ||
1109 | |||
1110 | connector->state->state = state; | ||
1111 | swap(state->connector_states[i], connector->state); | ||
1112 | connector->state->state = NULL; | ||
1113 | } | ||
1114 | |||
1115 | for (i = 0; i < dev->mode_config.num_crtc; i++) { | ||
1116 | struct drm_crtc *crtc = state->crtcs[i]; | ||
1117 | |||
1118 | if (!crtc) | ||
1119 | continue; | ||
1120 | |||
1121 | crtc->state->state = state; | ||
1122 | swap(state->crtc_states[i], crtc->state); | ||
1123 | crtc->state->state = NULL; | ||
1124 | } | ||
1125 | |||
1126 | for (i = 0; i < dev->mode_config.num_total_plane; i++) { | ||
1127 | struct drm_plane *plane = state->planes[i]; | ||
1128 | |||
1129 | if (!plane) | ||
1130 | continue; | ||
1131 | |||
1132 | plane->state->state = state; | ||
1133 | swap(state->plane_states[i], plane->state); | ||
1134 | plane->state->state = NULL; | ||
1135 | } | ||
1136 | } | ||
1137 | EXPORT_SYMBOL(drm_atomic_helper_swap_state); | ||
1138 | |||
1139 | /** | ||
1140 | * drm_atomic_helper_update_plane - Helper for primary plane update using atomic | ||
1141 | * @plane: plane object to update | ||
1142 | * @crtc: owning CRTC of owning plane | ||
1143 | * @fb: framebuffer to flip onto plane | ||
1144 | * @crtc_x: x offset of primary plane on crtc | ||
1145 | * @crtc_y: y offset of primary plane on crtc | ||
1146 | * @crtc_w: width of primary plane rectangle on crtc | ||
1147 | * @crtc_h: height of primary plane rectangle on crtc | ||
1148 | * @src_x: x offset of @fb for panning | ||
1149 | * @src_y: y offset of @fb for panning | ||
1150 | * @src_w: width of source rectangle in @fb | ||
1151 | * @src_h: height of source rectangle in @fb | ||
1152 | * | ||
1153 | * Provides a default plane update handler using the atomic driver interface. | ||
1154 | * | ||
1155 | * RETURNS: | ||
1156 | * Zero on success, error code on failure | ||
1157 | */ | ||
1158 | int drm_atomic_helper_update_plane(struct drm_plane *plane, | ||
1159 | struct drm_crtc *crtc, | ||
1160 | struct drm_framebuffer *fb, | ||
1161 | int crtc_x, int crtc_y, | ||
1162 | unsigned int crtc_w, unsigned int crtc_h, | ||
1163 | uint32_t src_x, uint32_t src_y, | ||
1164 | uint32_t src_w, uint32_t src_h) | ||
1165 | { | ||
1166 | struct drm_atomic_state *state; | ||
1167 | struct drm_plane_state *plane_state; | ||
1168 | int ret = 0; | ||
1169 | |||
1170 | state = drm_atomic_state_alloc(plane->dev); | ||
1171 | if (!state) | ||
1172 | return -ENOMEM; | ||
1173 | |||
1174 | state->acquire_ctx = drm_modeset_legacy_acquire_ctx(crtc); | ||
1175 | retry: | ||
1176 | plane_state = drm_atomic_get_plane_state(state, plane); | ||
1177 | if (IS_ERR(plane_state)) { | ||
1178 | ret = PTR_ERR(plane_state); | ||
1179 | goto fail; | ||
1180 | } | ||
1181 | |||
1182 | ret = drm_atomic_set_crtc_for_plane(plane_state, crtc); | ||
1183 | if (ret != 0) | ||
1184 | goto fail; | ||
1185 | drm_atomic_set_fb_for_plane(plane_state, fb); | ||
1186 | plane_state->crtc_x = crtc_x; | ||
1187 | plane_state->crtc_y = crtc_y; | ||
1188 | plane_state->crtc_h = crtc_h; | ||
1189 | plane_state->crtc_w = crtc_w; | ||
1190 | plane_state->src_x = src_x; | ||
1191 | plane_state->src_y = src_y; | ||
1192 | plane_state->src_h = src_h; | ||
1193 | plane_state->src_w = src_w; | ||
1194 | |||
1195 | ret = drm_atomic_commit(state); | ||
1196 | if (ret != 0) | ||
1197 | goto fail; | ||
1198 | |||
1199 | /* Driver takes ownership of state on successful commit. */ | ||
1200 | return 0; | ||
1201 | fail: | ||
1202 | if (ret == -EDEADLK) | ||
1203 | goto backoff; | ||
1204 | |||
1205 | drm_atomic_state_free(state); | ||
1206 | |||
1207 | return ret; | ||
1208 | backoff: | ||
1209 | drm_atomic_legacy_backoff(state); | ||
1210 | drm_atomic_state_clear(state); | ||
1211 | |||
1212 | /* | ||
1213 | * Someone might have exchanged the framebuffer while we dropped locks | ||
1214 | * in the backoff code. We need to fix up the fb refcount tracking the | ||
1215 | * core does for us. | ||
1216 | */ | ||
1217 | plane->old_fb = plane->fb; | ||
1218 | |||
1219 | goto retry; | ||
1220 | } | ||
1221 | EXPORT_SYMBOL(drm_atomic_helper_update_plane); | ||
1222 | |||
1223 | /** | ||
1224 | * drm_atomic_helper_disable_plane - Helper for primary plane disable using * atomic | ||
1225 | * @plane: plane to disable | ||
1226 | * | ||
1227 | * Provides a default plane disable handler using the atomic driver interface. | ||
1228 | * | ||
1229 | * RETURNS: | ||
1230 | * Zero on success, error code on failure | ||
1231 | */ | ||
1232 | int drm_atomic_helper_disable_plane(struct drm_plane *plane) | ||
1233 | { | ||
1234 | struct drm_atomic_state *state; | ||
1235 | struct drm_plane_state *plane_state; | ||
1236 | int ret = 0; | ||
1237 | |||
1238 | state = drm_atomic_state_alloc(plane->dev); | ||
1239 | if (!state) | ||
1240 | return -ENOMEM; | ||
1241 | |||
1242 | state->acquire_ctx = drm_modeset_legacy_acquire_ctx(plane->crtc); | ||
1243 | retry: | ||
1244 | plane_state = drm_atomic_get_plane_state(state, plane); | ||
1245 | if (IS_ERR(plane_state)) { | ||
1246 | ret = PTR_ERR(plane_state); | ||
1247 | goto fail; | ||
1248 | } | ||
1249 | |||
1250 | ret = drm_atomic_set_crtc_for_plane(plane_state, NULL); | ||
1251 | if (ret != 0) | ||
1252 | goto fail; | ||
1253 | drm_atomic_set_fb_for_plane(plane_state, NULL); | ||
1254 | plane_state->crtc_x = 0; | ||
1255 | plane_state->crtc_y = 0; | ||
1256 | plane_state->crtc_h = 0; | ||
1257 | plane_state->crtc_w = 0; | ||
1258 | plane_state->src_x = 0; | ||
1259 | plane_state->src_y = 0; | ||
1260 | plane_state->src_h = 0; | ||
1261 | plane_state->src_w = 0; | ||
1262 | |||
1263 | ret = drm_atomic_commit(state); | ||
1264 | if (ret != 0) | ||
1265 | goto fail; | ||
1266 | |||
1267 | /* Driver takes ownership of state on successful commit. */ | ||
1268 | return 0; | ||
1269 | fail: | ||
1270 | if (ret == -EDEADLK) | ||
1271 | goto backoff; | ||
1272 | |||
1273 | drm_atomic_state_free(state); | ||
1274 | |||
1275 | return ret; | ||
1276 | backoff: | ||
1277 | drm_atomic_legacy_backoff(state); | ||
1278 | drm_atomic_state_clear(state); | ||
1279 | |||
1280 | /* | ||
1281 | * Someone might have exchanged the framebuffer while we dropped locks | ||
1282 | * in the backoff code. We need to fix up the fb refcount tracking the | ||
1283 | * core does for us. | ||
1284 | */ | ||
1285 | plane->old_fb = plane->fb; | ||
1286 | |||
1287 | goto retry; | ||
1288 | } | ||
1289 | EXPORT_SYMBOL(drm_atomic_helper_disable_plane); | ||
1290 | |||
1291 | static int update_output_state(struct drm_atomic_state *state, | ||
1292 | struct drm_mode_set *set) | ||
1293 | { | ||
1294 | struct drm_device *dev = set->crtc->dev; | ||
1295 | struct drm_connector_state *conn_state; | ||
1296 | int nconnectors = state->dev->mode_config.num_connector; | ||
1297 | int ncrtcs = state->dev->mode_config.num_crtc; | ||
1298 | int ret, i, j; | ||
1299 | |||
1300 | ret = drm_modeset_lock(&dev->mode_config.connection_mutex, | ||
1301 | state->acquire_ctx); | ||
1302 | if (ret) | ||
1303 | return ret; | ||
1304 | |||
1305 | /* First grab all affected connector/crtc states. */ | ||
1306 | for (i = 0; i < set->num_connectors; i++) { | ||
1307 | conn_state = drm_atomic_get_connector_state(state, | ||
1308 | set->connectors[i]); | ||
1309 | if (IS_ERR(conn_state)) | ||
1310 | return PTR_ERR(conn_state); | ||
1311 | } | ||
1312 | |||
1313 | for (i = 0; i < ncrtcs; i++) { | ||
1314 | struct drm_crtc *crtc = state->crtcs[i]; | ||
1315 | |||
1316 | if (!crtc) | ||
1317 | continue; | ||
1318 | |||
1319 | ret = drm_atomic_add_affected_connectors(state, crtc); | ||
1320 | if (ret) | ||
1321 | return ret; | ||
1322 | } | ||
1323 | |||
1324 | /* Then recompute connector->crtc links and crtc enabling state. */ | ||
1325 | for (i = 0; i < nconnectors; i++) { | ||
1326 | struct drm_connector *connector; | ||
1327 | |||
1328 | connector = state->connectors[i]; | ||
1329 | conn_state = state->connector_states[i]; | ||
1330 | |||
1331 | if (!connector) | ||
1332 | continue; | ||
1333 | |||
1334 | if (conn_state->crtc == set->crtc) { | ||
1335 | ret = drm_atomic_set_crtc_for_connector(conn_state, | ||
1336 | NULL); | ||
1337 | if (ret) | ||
1338 | return ret; | ||
1339 | } | ||
1340 | |||
1341 | for (j = 0; j < set->num_connectors; j++) { | ||
1342 | if (set->connectors[j] == connector) { | ||
1343 | ret = drm_atomic_set_crtc_for_connector(conn_state, | ||
1344 | set->crtc); | ||
1345 | if (ret) | ||
1346 | return ret; | ||
1347 | break; | ||
1348 | } | ||
1349 | } | ||
1350 | } | ||
1351 | |||
1352 | for (i = 0; i < ncrtcs; i++) { | ||
1353 | struct drm_crtc *crtc = state->crtcs[i]; | ||
1354 | struct drm_crtc_state *crtc_state = state->crtc_states[i]; | ||
1355 | |||
1356 | if (!crtc) | ||
1357 | continue; | ||
1358 | |||
1359 | /* Don't update ->enable for the CRTC in the set_config request, | ||
1360 | * since a mismatch would indicate a bug in the upper layers. | ||
1361 | * The actual modeset code later on will catch any | ||
1362 | * inconsistencies here. */ | ||
1363 | if (crtc == set->crtc) | ||
1364 | continue; | ||
1365 | |||
1366 | crtc_state->enable = | ||
1367 | drm_atomic_connectors_for_crtc(state, crtc); | ||
1368 | } | ||
1369 | |||
1370 | return 0; | ||
1371 | } | ||
1372 | |||
1373 | /** | ||
1374 | * drm_atomic_helper_set_config - set a new config from userspace | ||
1375 | * @set: mode set configuration | ||
1376 | * | ||
1377 | * Provides a default crtc set_config handler using the atomic driver interface. | ||
1378 | * | ||
1379 | * Returns: | ||
1380 | * Returns 0 on success, negative errno numbers on failure. | ||
1381 | */ | ||
1382 | int drm_atomic_helper_set_config(struct drm_mode_set *set) | ||
1383 | { | ||
1384 | struct drm_atomic_state *state; | ||
1385 | struct drm_crtc *crtc = set->crtc; | ||
1386 | struct drm_crtc_state *crtc_state; | ||
1387 | struct drm_plane_state *primary_state; | ||
1388 | int ret = 0; | ||
1389 | |||
1390 | state = drm_atomic_state_alloc(crtc->dev); | ||
1391 | if (!state) | ||
1392 | return -ENOMEM; | ||
1393 | |||
1394 | state->acquire_ctx = drm_modeset_legacy_acquire_ctx(crtc); | ||
1395 | retry: | ||
1396 | crtc_state = drm_atomic_get_crtc_state(state, crtc); | ||
1397 | if (IS_ERR(crtc_state)) { | ||
1398 | ret = PTR_ERR(crtc_state); | ||
1399 | goto fail; | ||
1400 | } | ||
1401 | |||
1402 | if (!set->mode) { | ||
1403 | WARN_ON(set->fb); | ||
1404 | WARN_ON(set->num_connectors); | ||
1405 | |||
1406 | crtc_state->enable = false; | ||
1407 | goto commit; | ||
1408 | } | ||
1409 | |||
1410 | WARN_ON(!set->fb); | ||
1411 | WARN_ON(!set->num_connectors); | ||
1412 | |||
1413 | crtc_state->enable = true; | ||
1414 | drm_mode_copy(&crtc_state->mode, set->mode); | ||
1415 | |||
1416 | primary_state = drm_atomic_get_plane_state(state, crtc->primary); | ||
1417 | if (IS_ERR(primary_state)) { | ||
1418 | ret = PTR_ERR(primary_state); | ||
1419 | goto fail; | ||
1420 | } | ||
1421 | |||
1422 | ret = drm_atomic_set_crtc_for_plane(primary_state, crtc); | ||
1423 | if (ret != 0) | ||
1424 | goto fail; | ||
1425 | drm_atomic_set_fb_for_plane(primary_state, set->fb); | ||
1426 | primary_state->crtc_x = 0; | ||
1427 | primary_state->crtc_y = 0; | ||
1428 | primary_state->crtc_h = set->mode->vdisplay; | ||
1429 | primary_state->crtc_w = set->mode->hdisplay; | ||
1430 | primary_state->src_x = set->x << 16; | ||
1431 | primary_state->src_y = set->y << 16; | ||
1432 | primary_state->src_h = set->mode->vdisplay << 16; | ||
1433 | primary_state->src_w = set->mode->hdisplay << 16; | ||
1434 | |||
1435 | commit: | ||
1436 | ret = update_output_state(state, set); | ||
1437 | if (ret) | ||
1438 | goto fail; | ||
1439 | |||
1440 | ret = drm_atomic_commit(state); | ||
1441 | if (ret != 0) | ||
1442 | goto fail; | ||
1443 | |||
1444 | /* Driver takes ownership of state on successful commit. */ | ||
1445 | return 0; | ||
1446 | fail: | ||
1447 | if (ret == -EDEADLK) | ||
1448 | goto backoff; | ||
1449 | |||
1450 | drm_atomic_state_free(state); | ||
1451 | |||
1452 | return ret; | ||
1453 | backoff: | ||
1454 | drm_atomic_legacy_backoff(state); | ||
1455 | drm_atomic_state_clear(state); | ||
1456 | |||
1457 | /* | ||
1458 | * Someone might have exchanged the framebuffer while we dropped locks | ||
1459 | * in the backoff code. We need to fix up the fb refcount tracking the | ||
1460 | * core does for us. | ||
1461 | */ | ||
1462 | crtc->primary->old_fb = crtc->primary->fb; | ||
1463 | |||
1464 | goto retry; | ||
1465 | } | ||
1466 | EXPORT_SYMBOL(drm_atomic_helper_set_config); | ||
1467 | |||
1468 | /** | ||
1469 | * drm_atomic_helper_crtc_set_property - helper for crtc prorties | ||
1470 | * @crtc: DRM crtc | ||
1471 | * @property: DRM property | ||
1472 | * @val: value of property | ||
1473 | * | ||
1474 | * Provides a default plane disablle handler using the atomic driver interface. | ||
1475 | * | ||
1476 | * RETURNS: | ||
1477 | * Zero on success, error code on failure | ||
1478 | */ | ||
1479 | int | ||
1480 | drm_atomic_helper_crtc_set_property(struct drm_crtc *crtc, | ||
1481 | struct drm_property *property, | ||
1482 | uint64_t val) | ||
1483 | { | ||
1484 | struct drm_atomic_state *state; | ||
1485 | struct drm_crtc_state *crtc_state; | ||
1486 | int ret = 0; | ||
1487 | |||
1488 | state = drm_atomic_state_alloc(crtc->dev); | ||
1489 | if (!state) | ||
1490 | return -ENOMEM; | ||
1491 | |||
1492 | /* ->set_property is always called with all locks held. */ | ||
1493 | state->acquire_ctx = crtc->dev->mode_config.acquire_ctx; | ||
1494 | retry: | ||
1495 | crtc_state = drm_atomic_get_crtc_state(state, crtc); | ||
1496 | if (IS_ERR(crtc_state)) { | ||
1497 | ret = PTR_ERR(crtc_state); | ||
1498 | goto fail; | ||
1499 | } | ||
1500 | |||
1501 | ret = crtc->funcs->atomic_set_property(crtc, crtc_state, | ||
1502 | property, val); | ||
1503 | if (ret) | ||
1504 | goto fail; | ||
1505 | |||
1506 | ret = drm_atomic_commit(state); | ||
1507 | if (ret != 0) | ||
1508 | goto fail; | ||
1509 | |||
1510 | /* Driver takes ownership of state on successful commit. */ | ||
1511 | return 0; | ||
1512 | fail: | ||
1513 | if (ret == -EDEADLK) | ||
1514 | goto backoff; | ||
1515 | |||
1516 | drm_atomic_state_free(state); | ||
1517 | |||
1518 | return ret; | ||
1519 | backoff: | ||
1520 | drm_atomic_legacy_backoff(state); | ||
1521 | drm_atomic_state_clear(state); | ||
1522 | |||
1523 | goto retry; | ||
1524 | } | ||
1525 | EXPORT_SYMBOL(drm_atomic_helper_crtc_set_property); | ||
1526 | |||
1527 | /** | ||
1528 | * drm_atomic_helper_plane_set_property - helper for plane prorties | ||
1529 | * @plane: DRM plane | ||
1530 | * @property: DRM property | ||
1531 | * @val: value of property | ||
1532 | * | ||
1533 | * Provides a default plane disable handler using the atomic driver interface. | ||
1534 | * | ||
1535 | * RETURNS: | ||
1536 | * Zero on success, error code on failure | ||
1537 | */ | ||
1538 | int | ||
1539 | drm_atomic_helper_plane_set_property(struct drm_plane *plane, | ||
1540 | struct drm_property *property, | ||
1541 | uint64_t val) | ||
1542 | { | ||
1543 | struct drm_atomic_state *state; | ||
1544 | struct drm_plane_state *plane_state; | ||
1545 | int ret = 0; | ||
1546 | |||
1547 | state = drm_atomic_state_alloc(plane->dev); | ||
1548 | if (!state) | ||
1549 | return -ENOMEM; | ||
1550 | |||
1551 | /* ->set_property is always called with all locks held. */ | ||
1552 | state->acquire_ctx = plane->dev->mode_config.acquire_ctx; | ||
1553 | retry: | ||
1554 | plane_state = drm_atomic_get_plane_state(state, plane); | ||
1555 | if (IS_ERR(plane_state)) { | ||
1556 | ret = PTR_ERR(plane_state); | ||
1557 | goto fail; | ||
1558 | } | ||
1559 | |||
1560 | ret = plane->funcs->atomic_set_property(plane, plane_state, | ||
1561 | property, val); | ||
1562 | if (ret) | ||
1563 | goto fail; | ||
1564 | |||
1565 | ret = drm_atomic_commit(state); | ||
1566 | if (ret != 0) | ||
1567 | goto fail; | ||
1568 | |||
1569 | /* Driver takes ownership of state on successful commit. */ | ||
1570 | return 0; | ||
1571 | fail: | ||
1572 | if (ret == -EDEADLK) | ||
1573 | goto backoff; | ||
1574 | |||
1575 | drm_atomic_state_free(state); | ||
1576 | |||
1577 | return ret; | ||
1578 | backoff: | ||
1579 | drm_atomic_legacy_backoff(state); | ||
1580 | drm_atomic_state_clear(state); | ||
1581 | |||
1582 | goto retry; | ||
1583 | } | ||
1584 | EXPORT_SYMBOL(drm_atomic_helper_plane_set_property); | ||
1585 | |||
1586 | /** | ||
1587 | * drm_atomic_helper_connector_set_property - helper for connector prorties | ||
1588 | * @connector: DRM connector | ||
1589 | * @property: DRM property | ||
1590 | * @val: value of property | ||
1591 | * | ||
1592 | * Provides a default plane disablle handler using the atomic driver interface. | ||
1593 | * | ||
1594 | * RETURNS: | ||
1595 | * Zero on success, error code on failure | ||
1596 | */ | ||
1597 | int | ||
1598 | drm_atomic_helper_connector_set_property(struct drm_connector *connector, | ||
1599 | struct drm_property *property, | ||
1600 | uint64_t val) | ||
1601 | { | ||
1602 | struct drm_atomic_state *state; | ||
1603 | struct drm_connector_state *connector_state; | ||
1604 | int ret = 0; | ||
1605 | |||
1606 | state = drm_atomic_state_alloc(connector->dev); | ||
1607 | if (!state) | ||
1608 | return -ENOMEM; | ||
1609 | |||
1610 | /* ->set_property is always called with all locks held. */ | ||
1611 | state->acquire_ctx = connector->dev->mode_config.acquire_ctx; | ||
1612 | retry: | ||
1613 | connector_state = drm_atomic_get_connector_state(state, connector); | ||
1614 | if (IS_ERR(connector_state)) { | ||
1615 | ret = PTR_ERR(connector_state); | ||
1616 | goto fail; | ||
1617 | } | ||
1618 | |||
1619 | ret = connector->funcs->atomic_set_property(connector, connector_state, | ||
1620 | property, val); | ||
1621 | if (ret) | ||
1622 | goto fail; | ||
1623 | |||
1624 | ret = drm_atomic_commit(state); | ||
1625 | if (ret != 0) | ||
1626 | goto fail; | ||
1627 | |||
1628 | /* Driver takes ownership of state on successful commit. */ | ||
1629 | return 0; | ||
1630 | fail: | ||
1631 | if (ret == -EDEADLK) | ||
1632 | goto backoff; | ||
1633 | |||
1634 | drm_atomic_state_free(state); | ||
1635 | |||
1636 | return ret; | ||
1637 | backoff: | ||
1638 | drm_atomic_legacy_backoff(state); | ||
1639 | drm_atomic_state_clear(state); | ||
1640 | |||
1641 | goto retry; | ||
1642 | } | ||
1643 | EXPORT_SYMBOL(drm_atomic_helper_connector_set_property); | ||
1644 | |||
1645 | /** | ||
1646 | * drm_atomic_helper_page_flip - execute a legacy page flip | ||
1647 | * @crtc: DRM crtc | ||
1648 | * @fb: DRM framebuffer | ||
1649 | * @event: optional DRM event to signal upon completion | ||
1650 | * @flags: flip flags for non-vblank sync'ed updates | ||
1651 | * | ||
1652 | * Provides a default page flip implementation using the atomic driver interface. | ||
1653 | * | ||
1654 | * Note that for now so called async page flips (i.e. updates which are not | ||
1655 | * synchronized to vblank) are not supported, since the atomic interfaces have | ||
1656 | * no provisions for this yet. | ||
1657 | * | ||
1658 | * Returns: | ||
1659 | * Returns 0 on success, negative errno numbers on failure. | ||
1660 | */ | ||
1661 | int drm_atomic_helper_page_flip(struct drm_crtc *crtc, | ||
1662 | struct drm_framebuffer *fb, | ||
1663 | struct drm_pending_vblank_event *event, | ||
1664 | uint32_t flags) | ||
1665 | { | ||
1666 | struct drm_plane *plane = crtc->primary; | ||
1667 | struct drm_atomic_state *state; | ||
1668 | struct drm_plane_state *plane_state; | ||
1669 | struct drm_crtc_state *crtc_state; | ||
1670 | int ret = 0; | ||
1671 | |||
1672 | if (flags & DRM_MODE_PAGE_FLIP_ASYNC) | ||
1673 | return -EINVAL; | ||
1674 | |||
1675 | state = drm_atomic_state_alloc(plane->dev); | ||
1676 | if (!state) | ||
1677 | return -ENOMEM; | ||
1678 | |||
1679 | state->acquire_ctx = drm_modeset_legacy_acquire_ctx(crtc); | ||
1680 | retry: | ||
1681 | crtc_state = drm_atomic_get_crtc_state(state, crtc); | ||
1682 | if (IS_ERR(crtc_state)) { | ||
1683 | ret = PTR_ERR(crtc_state); | ||
1684 | goto fail; | ||
1685 | } | ||
1686 | crtc_state->event = event; | ||
1687 | |||
1688 | plane_state = drm_atomic_get_plane_state(state, plane); | ||
1689 | if (IS_ERR(plane_state)) { | ||
1690 | ret = PTR_ERR(plane_state); | ||
1691 | goto fail; | ||
1692 | } | ||
1693 | |||
1694 | ret = drm_atomic_set_crtc_for_plane(plane_state, crtc); | ||
1695 | if (ret != 0) | ||
1696 | goto fail; | ||
1697 | drm_atomic_set_fb_for_plane(plane_state, fb); | ||
1698 | |||
1699 | ret = drm_atomic_async_commit(state); | ||
1700 | if (ret != 0) | ||
1701 | goto fail; | ||
1702 | |||
1703 | /* TODO: ->page_flip is the only driver callback where the core | ||
1704 | * doesn't update plane->fb. For now patch it up here. */ | ||
1705 | plane->fb = plane->state->fb; | ||
1706 | |||
1707 | /* Driver takes ownership of state on successful async commit. */ | ||
1708 | return 0; | ||
1709 | fail: | ||
1710 | if (ret == -EDEADLK) | ||
1711 | goto backoff; | ||
1712 | |||
1713 | drm_atomic_state_free(state); | ||
1714 | |||
1715 | return ret; | ||
1716 | backoff: | ||
1717 | drm_atomic_legacy_backoff(state); | ||
1718 | drm_atomic_state_clear(state); | ||
1719 | |||
1720 | /* | ||
1721 | * Someone might have exchanged the framebuffer while we dropped locks | ||
1722 | * in the backoff code. We need to fix up the fb refcount tracking the | ||
1723 | * core does for us. | ||
1724 | */ | ||
1725 | plane->old_fb = plane->fb; | ||
1726 | |||
1727 | goto retry; | ||
1728 | } | ||
1729 | EXPORT_SYMBOL(drm_atomic_helper_page_flip); | ||
1730 | |||
1731 | /** | ||
1732 | * DOC: atomic state reset and initialization | ||
1733 | * | ||
1734 | * Both the drm core and the atomic helpers assume that there is always the full | ||
1735 | * and correct atomic software state for all connectors, CRTCs and planes | ||
1736 | * available. Which is a bit a problem on driver load and also after system | ||
1737 | * suspend. One way to solve this is to have a hardware state read-out | ||
1738 | * infrastructure which reconstructs the full software state (e.g. the i915 | ||
1739 | * driver). | ||
1740 | * | ||
1741 | * The simpler solution is to just reset the software state to everything off, | ||
1742 | * which is easiest to do by calling drm_mode_config_reset(). To facilitate this | ||
1743 | * the atomic helpers provide default reset implementations for all hooks. | ||
1744 | */ | ||
1745 | |||
1746 | /** | ||
1747 | * drm_atomic_helper_crtc_reset - default ->reset hook for CRTCs | ||
1748 | * @crtc: drm CRTC | ||
1749 | * | ||
1750 | * Resets the atomic state for @crtc by freeing the state pointer (which might | ||
1751 | * be NULL, e.g. at driver load time) and allocating a new empty state object. | ||
1752 | */ | ||
1753 | void drm_atomic_helper_crtc_reset(struct drm_crtc *crtc) | ||
1754 | { | ||
1755 | kfree(crtc->state); | ||
1756 | crtc->state = kzalloc(sizeof(*crtc->state), GFP_KERNEL); | ||
1757 | } | ||
1758 | EXPORT_SYMBOL(drm_atomic_helper_crtc_reset); | ||
1759 | |||
1760 | /** | ||
1761 | * drm_atomic_helper_crtc_duplicate_state - default state duplicate hook | ||
1762 | * @crtc: drm CRTC | ||
1763 | * | ||
1764 | * Default CRTC state duplicate hook for drivers which don't have their own | ||
1765 | * subclassed CRTC state structure. | ||
1766 | */ | ||
1767 | struct drm_crtc_state * | ||
1768 | drm_atomic_helper_crtc_duplicate_state(struct drm_crtc *crtc) | ||
1769 | { | ||
1770 | struct drm_crtc_state *state; | ||
1771 | |||
1772 | if (WARN_ON(!crtc->state)) | ||
1773 | return NULL; | ||
1774 | |||
1775 | state = kmemdup(crtc->state, sizeof(*crtc->state), GFP_KERNEL); | ||
1776 | |||
1777 | if (state) { | ||
1778 | state->mode_changed = false; | ||
1779 | state->planes_changed = false; | ||
1780 | state->event = NULL; | ||
1781 | } | ||
1782 | |||
1783 | return state; | ||
1784 | } | ||
1785 | EXPORT_SYMBOL(drm_atomic_helper_crtc_duplicate_state); | ||
1786 | |||
1787 | /** | ||
1788 | * drm_atomic_helper_crtc_destroy_state - default state destroy hook | ||
1789 | * @crtc: drm CRTC | ||
1790 | * @state: CRTC state object to release | ||
1791 | * | ||
1792 | * Default CRTC state destroy hook for drivers which don't have their own | ||
1793 | * subclassed CRTC state structure. | ||
1794 | */ | ||
1795 | void drm_atomic_helper_crtc_destroy_state(struct drm_crtc *crtc, | ||
1796 | struct drm_crtc_state *state) | ||
1797 | { | ||
1798 | kfree(state); | ||
1799 | } | ||
1800 | EXPORT_SYMBOL(drm_atomic_helper_crtc_destroy_state); | ||
1801 | |||
1802 | /** | ||
1803 | * drm_atomic_helper_plane_reset - default ->reset hook for planes | ||
1804 | * @plane: drm plane | ||
1805 | * | ||
1806 | * Resets the atomic state for @plane by freeing the state pointer (which might | ||
1807 | * be NULL, e.g. at driver load time) and allocating a new empty state object. | ||
1808 | */ | ||
1809 | void drm_atomic_helper_plane_reset(struct drm_plane *plane) | ||
1810 | { | ||
1811 | if (plane->state && plane->state->fb) | ||
1812 | drm_framebuffer_unreference(plane->state->fb); | ||
1813 | |||
1814 | kfree(plane->state); | ||
1815 | plane->state = kzalloc(sizeof(*plane->state), GFP_KERNEL); | ||
1816 | } | ||
1817 | EXPORT_SYMBOL(drm_atomic_helper_plane_reset); | ||
1818 | |||
1819 | /** | ||
1820 | * drm_atomic_helper_plane_duplicate_state - default state duplicate hook | ||
1821 | * @plane: drm plane | ||
1822 | * | ||
1823 | * Default plane state duplicate hook for drivers which don't have their own | ||
1824 | * subclassed plane state structure. | ||
1825 | */ | ||
1826 | struct drm_plane_state * | ||
1827 | drm_atomic_helper_plane_duplicate_state(struct drm_plane *plane) | ||
1828 | { | ||
1829 | struct drm_plane_state *state; | ||
1830 | |||
1831 | if (WARN_ON(!plane->state)) | ||
1832 | return NULL; | ||
1833 | |||
1834 | state = kmemdup(plane->state, sizeof(*plane->state), GFP_KERNEL); | ||
1835 | |||
1836 | if (state && state->fb) | ||
1837 | drm_framebuffer_reference(state->fb); | ||
1838 | |||
1839 | return state; | ||
1840 | } | ||
1841 | EXPORT_SYMBOL(drm_atomic_helper_plane_duplicate_state); | ||
1842 | |||
1843 | /** | ||
1844 | * drm_atomic_helper_plane_destroy_state - default state destroy hook | ||
1845 | * @plane: drm plane | ||
1846 | * @state: plane state object to release | ||
1847 | * | ||
1848 | * Default plane state destroy hook for drivers which don't have their own | ||
1849 | * subclassed plane state structure. | ||
1850 | */ | ||
1851 | void drm_atomic_helper_plane_destroy_state(struct drm_plane *plane, | ||
1852 | struct drm_plane_state *state) | ||
1853 | { | ||
1854 | if (state->fb) | ||
1855 | drm_framebuffer_unreference(state->fb); | ||
1856 | |||
1857 | kfree(state); | ||
1858 | } | ||
1859 | EXPORT_SYMBOL(drm_atomic_helper_plane_destroy_state); | ||
1860 | |||
1861 | /** | ||
1862 | * drm_atomic_helper_connector_reset - default ->reset hook for connectors | ||
1863 | * @connector: drm connector | ||
1864 | * | ||
1865 | * Resets the atomic state for @connector by freeing the state pointer (which | ||
1866 | * might be NULL, e.g. at driver load time) and allocating a new empty state | ||
1867 | * object. | ||
1868 | */ | ||
1869 | void drm_atomic_helper_connector_reset(struct drm_connector *connector) | ||
1870 | { | ||
1871 | kfree(connector->state); | ||
1872 | connector->state = kzalloc(sizeof(*connector->state), GFP_KERNEL); | ||
1873 | } | ||
1874 | EXPORT_SYMBOL(drm_atomic_helper_connector_reset); | ||
1875 | |||
1876 | /** | ||
1877 | * drm_atomic_helper_connector_duplicate_state - default state duplicate hook | ||
1878 | * @connector: drm connector | ||
1879 | * | ||
1880 | * Default connector state duplicate hook for drivers which don't have their own | ||
1881 | * subclassed connector state structure. | ||
1882 | */ | ||
1883 | struct drm_connector_state * | ||
1884 | drm_atomic_helper_connector_duplicate_state(struct drm_connector *connector) | ||
1885 | { | ||
1886 | if (WARN_ON(!connector->state)) | ||
1887 | return NULL; | ||
1888 | |||
1889 | return kmemdup(connector->state, sizeof(*connector->state), GFP_KERNEL); | ||
1890 | } | ||
1891 | EXPORT_SYMBOL(drm_atomic_helper_connector_duplicate_state); | ||
1892 | |||
1893 | /** | ||
1894 | * drm_atomic_helper_connector_destroy_state - default state destroy hook | ||
1895 | * @connector: drm connector | ||
1896 | * @state: connector state object to release | ||
1897 | * | ||
1898 | * Default connector state destroy hook for drivers which don't have their own | ||
1899 | * subclassed connector state structure. | ||
1900 | */ | ||
1901 | void drm_atomic_helper_connector_destroy_state(struct drm_connector *connector, | ||
1902 | struct drm_connector_state *state) | ||
1903 | { | ||
1904 | kfree(state); | ||
1905 | } | ||
1906 | EXPORT_SYMBOL(drm_atomic_helper_connector_destroy_state); | ||
diff --git a/drivers/gpu/drm/drm_crtc.c b/drivers/gpu/drm/drm_crtc.c index e79c8d3700d8..e6c169152bf1 100644 --- a/drivers/gpu/drm/drm_crtc.c +++ b/drivers/gpu/drm/drm_crtc.c | |||
@@ -766,7 +766,6 @@ static void drm_mode_remove(struct drm_connector *connector, | |||
766 | /** | 766 | /** |
767 | * drm_connector_get_cmdline_mode - reads the user's cmdline mode | 767 | * drm_connector_get_cmdline_mode - reads the user's cmdline mode |
768 | * @connector: connector to quwery | 768 | * @connector: connector to quwery |
769 | * @mode: returned mode | ||
770 | * | 769 | * |
771 | * The kernel supports per-connector configration of its consoles through | 770 | * The kernel supports per-connector configration of its consoles through |
772 | * use of the video= parameter. This function parses that option and | 771 | * use of the video= parameter. This function parses that option and |
@@ -2943,7 +2942,7 @@ EXPORT_SYMBOL(drm_mode_legacy_fb_format); | |||
2943 | * @file_priv: drm file for the ioctl call | 2942 | * @file_priv: drm file for the ioctl call |
2944 | * | 2943 | * |
2945 | * Add a new FB to the specified CRTC, given a user request. This is the | 2944 | * Add a new FB to the specified CRTC, given a user request. This is the |
2946 | * original addfb ioclt which only supported RGB formats. | 2945 | * original addfb ioctl which only supported RGB formats. |
2947 | * | 2946 | * |
2948 | * Called by the user via ioctl. | 2947 | * Called by the user via ioctl. |
2949 | * | 2948 | * |
@@ -2955,11 +2954,9 @@ int drm_mode_addfb(struct drm_device *dev, | |||
2955 | { | 2954 | { |
2956 | struct drm_mode_fb_cmd *or = data; | 2955 | struct drm_mode_fb_cmd *or = data; |
2957 | struct drm_mode_fb_cmd2 r = {}; | 2956 | struct drm_mode_fb_cmd2 r = {}; |
2958 | struct drm_mode_config *config = &dev->mode_config; | 2957 | int ret; |
2959 | struct drm_framebuffer *fb; | ||
2960 | int ret = 0; | ||
2961 | 2958 | ||
2962 | /* Use new struct with format internally */ | 2959 | /* convert to new format and call new ioctl */ |
2963 | r.fb_id = or->fb_id; | 2960 | r.fb_id = or->fb_id; |
2964 | r.width = or->width; | 2961 | r.width = or->width; |
2965 | r.height = or->height; | 2962 | r.height = or->height; |
@@ -2967,26 +2964,11 @@ int drm_mode_addfb(struct drm_device *dev, | |||
2967 | r.pixel_format = drm_mode_legacy_fb_format(or->bpp, or->depth); | 2964 | r.pixel_format = drm_mode_legacy_fb_format(or->bpp, or->depth); |
2968 | r.handles[0] = or->handle; | 2965 | r.handles[0] = or->handle; |
2969 | 2966 | ||
2970 | if (!drm_core_check_feature(dev, DRIVER_MODESET)) | 2967 | ret = drm_mode_addfb2(dev, &r, file_priv); |
2971 | return -EINVAL; | 2968 | if (ret) |
2972 | 2969 | return ret; | |
2973 | if ((config->min_width > r.width) || (r.width > config->max_width)) | ||
2974 | return -EINVAL; | ||
2975 | |||
2976 | if ((config->min_height > r.height) || (r.height > config->max_height)) | ||
2977 | return -EINVAL; | ||
2978 | |||
2979 | fb = dev->mode_config.funcs->fb_create(dev, file_priv, &r); | ||
2980 | if (IS_ERR(fb)) { | ||
2981 | DRM_DEBUG_KMS("could not create framebuffer\n"); | ||
2982 | return PTR_ERR(fb); | ||
2983 | } | ||
2984 | 2970 | ||
2985 | mutex_lock(&file_priv->fbs_lock); | 2971 | or->fb_id = r.fb_id; |
2986 | or->fb_id = fb->base.id; | ||
2987 | list_add(&fb->filp_head, &file_priv->fbs); | ||
2988 | DRM_DEBUG_KMS("[FB:%d]\n", fb->base.id); | ||
2989 | mutex_unlock(&file_priv->fbs_lock); | ||
2990 | 2972 | ||
2991 | return ret; | 2973 | return ret; |
2992 | } | 2974 | } |
@@ -3080,7 +3062,7 @@ static int framebuffer_check(const struct drm_mode_fb_cmd2 *r) | |||
3080 | num_planes = drm_format_num_planes(r->pixel_format); | 3062 | num_planes = drm_format_num_planes(r->pixel_format); |
3081 | 3063 | ||
3082 | if (r->width == 0 || r->width % hsub) { | 3064 | if (r->width == 0 || r->width % hsub) { |
3083 | DRM_DEBUG_KMS("bad framebuffer width %u\n", r->height); | 3065 | DRM_DEBUG_KMS("bad framebuffer width %u\n", r->width); |
3084 | return -EINVAL; | 3066 | return -EINVAL; |
3085 | } | 3067 | } |
3086 | 3068 | ||
@@ -3435,6 +3417,10 @@ void drm_fb_release(struct drm_file *priv) | |||
3435 | * object with drm_object_attach_property. The returned property object must be | 3417 | * object with drm_object_attach_property. The returned property object must be |
3436 | * freed with drm_property_destroy. | 3418 | * freed with drm_property_destroy. |
3437 | * | 3419 | * |
3420 | * Note that the DRM core keeps a per-device list of properties and that, if | ||
3421 | * drm_mode_config_cleanup() is called, it will destroy all properties created | ||
3422 | * by the driver. | ||
3423 | * | ||
3438 | * Returns: | 3424 | * Returns: |
3439 | * A pointer to the newly created property on success, NULL on failure. | 3425 | * A pointer to the newly created property on success, NULL on failure. |
3440 | */ | 3426 | */ |
@@ -3611,7 +3597,7 @@ static struct drm_property *property_create_range(struct drm_device *dev, | |||
3611 | * object with drm_object_attach_property. The returned property object must be | 3597 | * object with drm_object_attach_property. The returned property object must be |
3612 | * freed with drm_property_destroy. | 3598 | * freed with drm_property_destroy. |
3613 | * | 3599 | * |
3614 | * Userspace is allowed to set any interger value in the (min, max) range | 3600 | * Userspace is allowed to set any integer value in the (min, max) range |
3615 | * inclusive. | 3601 | * inclusive. |
3616 | * | 3602 | * |
3617 | * Returns: | 3603 | * Returns: |
@@ -4019,6 +4005,19 @@ done: | |||
4019 | return ret; | 4005 | return ret; |
4020 | } | 4006 | } |
4021 | 4007 | ||
4008 | /** | ||
4009 | * drm_mode_connector_set_path_property - set tile property on connector | ||
4010 | * @connector: connector to set property on. | ||
4011 | * @path: path to use for property. | ||
4012 | * | ||
4013 | * This creates a property to expose to userspace to specify a | ||
4014 | * connector path. This is mainly used for DisplayPort MST where | ||
4015 | * connectors have a topology and we want to allow userspace to give | ||
4016 | * them more meaningful names. | ||
4017 | * | ||
4018 | * Returns: | ||
4019 | * Zero on success, errno on failure. | ||
4020 | */ | ||
4022 | int drm_mode_connector_set_path_property(struct drm_connector *connector, | 4021 | int drm_mode_connector_set_path_property(struct drm_connector *connector, |
4023 | char *path) | 4022 | char *path) |
4024 | { | 4023 | { |
diff --git a/drivers/gpu/drm/drm_crtc_helper.c b/drivers/gpu/drm/drm_crtc_helper.c index 6c65a0a28fbd..d552708409de 100644 --- a/drivers/gpu/drm/drm_crtc_helper.c +++ b/drivers/gpu/drm/drm_crtc_helper.c | |||
@@ -34,12 +34,35 @@ | |||
34 | #include <linux/moduleparam.h> | 34 | #include <linux/moduleparam.h> |
35 | 35 | ||
36 | #include <drm/drmP.h> | 36 | #include <drm/drmP.h> |
37 | #include <drm/drm_atomic.h> | ||
37 | #include <drm/drm_crtc.h> | 38 | #include <drm/drm_crtc.h> |
38 | #include <drm/drm_fourcc.h> | 39 | #include <drm/drm_fourcc.h> |
39 | #include <drm/drm_crtc_helper.h> | 40 | #include <drm/drm_crtc_helper.h> |
40 | #include <drm/drm_fb_helper.h> | 41 | #include <drm/drm_fb_helper.h> |
42 | #include <drm/drm_plane_helper.h> | ||
43 | #include <drm/drm_atomic_helper.h> | ||
41 | #include <drm/drm_edid.h> | 44 | #include <drm/drm_edid.h> |
42 | 45 | ||
46 | /** | ||
47 | * DOC: overview | ||
48 | * | ||
49 | * The CRTC modeset helper library provides a default set_config implementation | ||
50 | * in drm_crtc_helper_set_config(). Plus a few other convenience functions using | ||
51 | * the same callbacks which drivers can use to e.g. restore the modeset | ||
52 | * configuration on resume with drm_helper_resume_force_mode(). | ||
53 | * | ||
54 | * The driver callbacks are mostly compatible with the atomic modeset helpers, | ||
55 | * except for the handling of the primary plane: Atomic helpers require that the | ||
56 | * primary plane is implemented as a real standalone plane and not directly tied | ||
57 | * to the CRTC state. For easier transition this library provides functions to | ||
58 | * implement the old semantics required by the CRTC helpers using the new plane | ||
59 | * and atomic helper callbacks. | ||
60 | * | ||
61 | * Drivers are strongly urged to convert to the atomic helpers (by way of first | ||
62 | * converting to the plane helpers). New drivers must not use these functions | ||
63 | * but need to implement the atomic interface instead, potentially using the | ||
64 | * atomic helpers for that. | ||
65 | */ | ||
43 | MODULE_AUTHOR("David Airlie, Jesse Barnes"); | 66 | MODULE_AUTHOR("David Airlie, Jesse Barnes"); |
44 | MODULE_DESCRIPTION("DRM KMS helper"); | 67 | MODULE_DESCRIPTION("DRM KMS helper"); |
45 | MODULE_LICENSE("GPL and additional rights"); | 68 | MODULE_LICENSE("GPL and additional rights"); |
@@ -888,3 +911,112 @@ void drm_helper_resume_force_mode(struct drm_device *dev) | |||
888 | drm_modeset_unlock_all(dev); | 911 | drm_modeset_unlock_all(dev); |
889 | } | 912 | } |
890 | EXPORT_SYMBOL(drm_helper_resume_force_mode); | 913 | EXPORT_SYMBOL(drm_helper_resume_force_mode); |
914 | |||
915 | /** | ||
916 | * drm_helper_crtc_mode_set - mode_set implementation for atomic plane helpers | ||
917 | * @crtc: DRM CRTC | ||
918 | * @mode: DRM display mode which userspace requested | ||
919 | * @adjusted_mode: DRM display mode adjusted by ->mode_fixup callbacks | ||
920 | * @x: x offset of the CRTC scanout area on the underlying framebuffer | ||
921 | * @y: y offset of the CRTC scanout area on the underlying framebuffer | ||
922 | * @old_fb: previous framebuffer | ||
923 | * | ||
924 | * This function implements a callback useable as the ->mode_set callback | ||
925 | * required by the crtc helpers. Besides the atomic plane helper functions for | ||
926 | * the primary plane the driver must also provide the ->mode_set_nofb callback | ||
927 | * to set up the crtc. | ||
928 | * | ||
929 | * This is a transitional helper useful for converting drivers to the atomic | ||
930 | * interfaces. | ||
931 | */ | ||
932 | int drm_helper_crtc_mode_set(struct drm_crtc *crtc, struct drm_display_mode *mode, | ||
933 | struct drm_display_mode *adjusted_mode, int x, int y, | ||
934 | struct drm_framebuffer *old_fb) | ||
935 | { | ||
936 | struct drm_crtc_state *crtc_state; | ||
937 | struct drm_crtc_helper_funcs *crtc_funcs = crtc->helper_private; | ||
938 | int ret; | ||
939 | |||
940 | if (crtc->funcs->atomic_duplicate_state) | ||
941 | crtc_state = crtc->funcs->atomic_duplicate_state(crtc); | ||
942 | else if (crtc->state) | ||
943 | crtc_state = kmemdup(crtc->state, sizeof(*crtc_state), | ||
944 | GFP_KERNEL); | ||
945 | else | ||
946 | crtc_state = kzalloc(sizeof(*crtc_state), GFP_KERNEL); | ||
947 | if (!crtc_state) | ||
948 | return -ENOMEM; | ||
949 | |||
950 | crtc_state->enable = true; | ||
951 | crtc_state->planes_changed = true; | ||
952 | crtc_state->mode_changed = true; | ||
953 | drm_mode_copy(&crtc_state->mode, mode); | ||
954 | drm_mode_copy(&crtc_state->adjusted_mode, adjusted_mode); | ||
955 | |||
956 | if (crtc_funcs->atomic_check) { | ||
957 | ret = crtc_funcs->atomic_check(crtc, crtc_state); | ||
958 | if (ret) { | ||
959 | kfree(crtc_state); | ||
960 | |||
961 | return ret; | ||
962 | } | ||
963 | } | ||
964 | |||
965 | swap(crtc->state, crtc_state); | ||
966 | |||
967 | crtc_funcs->mode_set_nofb(crtc); | ||
968 | |||
969 | if (crtc_state) { | ||
970 | if (crtc->funcs->atomic_destroy_state) | ||
971 | crtc->funcs->atomic_destroy_state(crtc, crtc_state); | ||
972 | else | ||
973 | kfree(crtc_state); | ||
974 | } | ||
975 | |||
976 | return drm_helper_crtc_mode_set_base(crtc, x, y, old_fb); | ||
977 | } | ||
978 | EXPORT_SYMBOL(drm_helper_crtc_mode_set); | ||
979 | |||
980 | /** | ||
981 | * drm_helper_crtc_mode_set_base - mode_set_base implementation for atomic plane helpers | ||
982 | * @crtc: DRM CRTC | ||
983 | * @x: x offset of the CRTC scanout area on the underlying framebuffer | ||
984 | * @y: y offset of the CRTC scanout area on the underlying framebuffer | ||
985 | * @old_fb: previous framebuffer | ||
986 | * | ||
987 | * This function implements a callback useable as the ->mode_set_base used | ||
988 | * required by the crtc helpers. The driver must provide the atomic plane helper | ||
989 | * functions for the primary plane. | ||
990 | * | ||
991 | * This is a transitional helper useful for converting drivers to the atomic | ||
992 | * interfaces. | ||
993 | */ | ||
994 | int drm_helper_crtc_mode_set_base(struct drm_crtc *crtc, int x, int y, | ||
995 | struct drm_framebuffer *old_fb) | ||
996 | { | ||
997 | struct drm_plane_state *plane_state; | ||
998 | struct drm_plane *plane = crtc->primary; | ||
999 | |||
1000 | if (plane->funcs->atomic_duplicate_state) | ||
1001 | plane_state = plane->funcs->atomic_duplicate_state(plane); | ||
1002 | else if (plane->state) | ||
1003 | plane_state = drm_atomic_helper_plane_duplicate_state(plane); | ||
1004 | else | ||
1005 | plane_state = kzalloc(sizeof(*plane_state), GFP_KERNEL); | ||
1006 | if (!plane_state) | ||
1007 | return -ENOMEM; | ||
1008 | |||
1009 | plane_state->crtc = crtc; | ||
1010 | drm_atomic_set_fb_for_plane(plane_state, crtc->primary->fb); | ||
1011 | plane_state->crtc_x = 0; | ||
1012 | plane_state->crtc_y = 0; | ||
1013 | plane_state->crtc_h = crtc->mode.vdisplay; | ||
1014 | plane_state->crtc_w = crtc->mode.hdisplay; | ||
1015 | plane_state->src_x = x << 16; | ||
1016 | plane_state->src_y = y << 16; | ||
1017 | plane_state->src_h = crtc->mode.vdisplay << 16; | ||
1018 | plane_state->src_w = crtc->mode.hdisplay << 16; | ||
1019 | |||
1020 | return drm_plane_helper_commit(plane, plane_state, old_fb); | ||
1021 | } | ||
1022 | EXPORT_SYMBOL(drm_helper_crtc_mode_set_base); | ||
diff --git a/drivers/gpu/drm/drm_dp_helper.c b/drivers/gpu/drm/drm_dp_helper.c index 08e33b8b13a4..959e2074b0d4 100644 --- a/drivers/gpu/drm/drm_dp_helper.c +++ b/drivers/gpu/drm/drm_dp_helper.c | |||
@@ -39,198 +39,6 @@ | |||
39 | * blocks, ... | 39 | * blocks, ... |
40 | */ | 40 | */ |
41 | 41 | ||
42 | /* Run a single AUX_CH I2C transaction, writing/reading data as necessary */ | ||
43 | static int | ||
44 | i2c_algo_dp_aux_transaction(struct i2c_adapter *adapter, int mode, | ||
45 | uint8_t write_byte, uint8_t *read_byte) | ||
46 | { | ||
47 | struct i2c_algo_dp_aux_data *algo_data = adapter->algo_data; | ||
48 | int ret; | ||
49 | |||
50 | ret = (*algo_data->aux_ch)(adapter, mode, | ||
51 | write_byte, read_byte); | ||
52 | return ret; | ||
53 | } | ||
54 | |||
55 | /* | ||
56 | * I2C over AUX CH | ||
57 | */ | ||
58 | |||
59 | /* | ||
60 | * Send the address. If the I2C link is running, this 'restarts' | ||
61 | * the connection with the new address, this is used for doing | ||
62 | * a write followed by a read (as needed for DDC) | ||
63 | */ | ||
64 | static int | ||
65 | i2c_algo_dp_aux_address(struct i2c_adapter *adapter, u16 address, bool reading) | ||
66 | { | ||
67 | struct i2c_algo_dp_aux_data *algo_data = adapter->algo_data; | ||
68 | int mode = MODE_I2C_START; | ||
69 | int ret; | ||
70 | |||
71 | if (reading) | ||
72 | mode |= MODE_I2C_READ; | ||
73 | else | ||
74 | mode |= MODE_I2C_WRITE; | ||
75 | algo_data->address = address; | ||
76 | algo_data->running = true; | ||
77 | ret = i2c_algo_dp_aux_transaction(adapter, mode, 0, NULL); | ||
78 | return ret; | ||
79 | } | ||
80 | |||
81 | /* | ||
82 | * Stop the I2C transaction. This closes out the link, sending | ||
83 | * a bare address packet with the MOT bit turned off | ||
84 | */ | ||
85 | static void | ||
86 | i2c_algo_dp_aux_stop(struct i2c_adapter *adapter, bool reading) | ||
87 | { | ||
88 | struct i2c_algo_dp_aux_data *algo_data = adapter->algo_data; | ||
89 | int mode = MODE_I2C_STOP; | ||
90 | |||
91 | if (reading) | ||
92 | mode |= MODE_I2C_READ; | ||
93 | else | ||
94 | mode |= MODE_I2C_WRITE; | ||
95 | if (algo_data->running) { | ||
96 | (void) i2c_algo_dp_aux_transaction(adapter, mode, 0, NULL); | ||
97 | algo_data->running = false; | ||
98 | } | ||
99 | } | ||
100 | |||
101 | /* | ||
102 | * Write a single byte to the current I2C address, the | ||
103 | * the I2C link must be running or this returns -EIO | ||
104 | */ | ||
105 | static int | ||
106 | i2c_algo_dp_aux_put_byte(struct i2c_adapter *adapter, u8 byte) | ||
107 | { | ||
108 | struct i2c_algo_dp_aux_data *algo_data = adapter->algo_data; | ||
109 | int ret; | ||
110 | |||
111 | if (!algo_data->running) | ||
112 | return -EIO; | ||
113 | |||
114 | ret = i2c_algo_dp_aux_transaction(adapter, MODE_I2C_WRITE, byte, NULL); | ||
115 | return ret; | ||
116 | } | ||
117 | |||
118 | /* | ||
119 | * Read a single byte from the current I2C address, the | ||
120 | * I2C link must be running or this returns -EIO | ||
121 | */ | ||
122 | static int | ||
123 | i2c_algo_dp_aux_get_byte(struct i2c_adapter *adapter, u8 *byte_ret) | ||
124 | { | ||
125 | struct i2c_algo_dp_aux_data *algo_data = adapter->algo_data; | ||
126 | int ret; | ||
127 | |||
128 | if (!algo_data->running) | ||
129 | return -EIO; | ||
130 | |||
131 | ret = i2c_algo_dp_aux_transaction(adapter, MODE_I2C_READ, 0, byte_ret); | ||
132 | return ret; | ||
133 | } | ||
134 | |||
135 | static int | ||
136 | i2c_algo_dp_aux_xfer(struct i2c_adapter *adapter, | ||
137 | struct i2c_msg *msgs, | ||
138 | int num) | ||
139 | { | ||
140 | int ret = 0; | ||
141 | bool reading = false; | ||
142 | int m; | ||
143 | int b; | ||
144 | |||
145 | for (m = 0; m < num; m++) { | ||
146 | u16 len = msgs[m].len; | ||
147 | u8 *buf = msgs[m].buf; | ||
148 | reading = (msgs[m].flags & I2C_M_RD) != 0; | ||
149 | ret = i2c_algo_dp_aux_address(adapter, msgs[m].addr, reading); | ||
150 | if (ret < 0) | ||
151 | break; | ||
152 | if (reading) { | ||
153 | for (b = 0; b < len; b++) { | ||
154 | ret = i2c_algo_dp_aux_get_byte(adapter, &buf[b]); | ||
155 | if (ret < 0) | ||
156 | break; | ||
157 | } | ||
158 | } else { | ||
159 | for (b = 0; b < len; b++) { | ||
160 | ret = i2c_algo_dp_aux_put_byte(adapter, buf[b]); | ||
161 | if (ret < 0) | ||
162 | break; | ||
163 | } | ||
164 | } | ||
165 | if (ret < 0) | ||
166 | break; | ||
167 | } | ||
168 | if (ret >= 0) | ||
169 | ret = num; | ||
170 | i2c_algo_dp_aux_stop(adapter, reading); | ||
171 | DRM_DEBUG_KMS("dp_aux_xfer return %d\n", ret); | ||
172 | return ret; | ||
173 | } | ||
174 | |||
175 | static u32 | ||
176 | i2c_algo_dp_aux_functionality(struct i2c_adapter *adapter) | ||
177 | { | ||
178 | return I2C_FUNC_I2C | I2C_FUNC_SMBUS_EMUL | | ||
179 | I2C_FUNC_SMBUS_READ_BLOCK_DATA | | ||
180 | I2C_FUNC_SMBUS_BLOCK_PROC_CALL | | ||
181 | I2C_FUNC_10BIT_ADDR; | ||
182 | } | ||
183 | |||
184 | static const struct i2c_algorithm i2c_dp_aux_algo = { | ||
185 | .master_xfer = i2c_algo_dp_aux_xfer, | ||
186 | .functionality = i2c_algo_dp_aux_functionality, | ||
187 | }; | ||
188 | |||
189 | static void | ||
190 | i2c_dp_aux_reset_bus(struct i2c_adapter *adapter) | ||
191 | { | ||
192 | (void) i2c_algo_dp_aux_address(adapter, 0, false); | ||
193 | (void) i2c_algo_dp_aux_stop(adapter, false); | ||
194 | } | ||
195 | |||
196 | static int | ||
197 | i2c_dp_aux_prepare_bus(struct i2c_adapter *adapter) | ||
198 | { | ||
199 | adapter->algo = &i2c_dp_aux_algo; | ||
200 | adapter->retries = 3; | ||
201 | i2c_dp_aux_reset_bus(adapter); | ||
202 | return 0; | ||
203 | } | ||
204 | |||
205 | /** | ||
206 | * i2c_dp_aux_add_bus() - register an i2c adapter using the aux ch helper | ||
207 | * @adapter: i2c adapter to register | ||
208 | * | ||
209 | * This registers an i2c adapter that uses dp aux channel as it's underlaying | ||
210 | * transport. The driver needs to fill out the &i2c_algo_dp_aux_data structure | ||
211 | * and store it in the algo_data member of the @adapter argument. This will be | ||
212 | * used by the i2c over dp aux algorithm to drive the hardware. | ||
213 | * | ||
214 | * RETURNS: | ||
215 | * 0 on success, -ERRNO on failure. | ||
216 | * | ||
217 | * IMPORTANT: | ||
218 | * This interface is deprecated, please switch to the new dp aux helpers and | ||
219 | * drm_dp_aux_register(). | ||
220 | */ | ||
221 | int | ||
222 | i2c_dp_aux_add_bus(struct i2c_adapter *adapter) | ||
223 | { | ||
224 | int error; | ||
225 | |||
226 | error = i2c_dp_aux_prepare_bus(adapter); | ||
227 | if (error) | ||
228 | return error; | ||
229 | error = i2c_add_adapter(adapter); | ||
230 | return error; | ||
231 | } | ||
232 | EXPORT_SYMBOL(i2c_dp_aux_add_bus); | ||
233 | |||
234 | /* Helpers for DP link training */ | 42 | /* Helpers for DP link training */ |
235 | static u8 dp_link_status(const u8 link_status[DP_LINK_STATUS_SIZE], int r) | 43 | static u8 dp_link_status(const u8 link_status[DP_LINK_STATUS_SIZE], int r) |
236 | { | 44 | { |
@@ -654,10 +462,12 @@ static int drm_dp_i2c_do_msg(struct drm_dp_aux *aux, struct drm_dp_aux_msg *msg) | |||
654 | 462 | ||
655 | case DP_AUX_I2C_REPLY_NACK: | 463 | case DP_AUX_I2C_REPLY_NACK: |
656 | DRM_DEBUG_KMS("I2C nack\n"); | 464 | DRM_DEBUG_KMS("I2C nack\n"); |
465 | aux->i2c_nack_count++; | ||
657 | return -EREMOTEIO; | 466 | return -EREMOTEIO; |
658 | 467 | ||
659 | case DP_AUX_I2C_REPLY_DEFER: | 468 | case DP_AUX_I2C_REPLY_DEFER: |
660 | DRM_DEBUG_KMS("I2C defer\n"); | 469 | DRM_DEBUG_KMS("I2C defer\n"); |
470 | aux->i2c_defer_count++; | ||
661 | usleep_range(400, 500); | 471 | usleep_range(400, 500); |
662 | continue; | 472 | continue; |
663 | 473 | ||
diff --git a/drivers/gpu/drm/drm_dp_mst_topology.c b/drivers/gpu/drm/drm_dp_mst_topology.c index 070f913d2dba..dc98b8f78168 100644 --- a/drivers/gpu/drm/drm_dp_mst_topology.c +++ b/drivers/gpu/drm/drm_dp_mst_topology.c | |||
@@ -1011,19 +1011,20 @@ static void drm_dp_check_port_guid(struct drm_dp_mst_branch *mstb, | |||
1011 | 1011 | ||
1012 | static void build_mst_prop_path(struct drm_dp_mst_port *port, | 1012 | static void build_mst_prop_path(struct drm_dp_mst_port *port, |
1013 | struct drm_dp_mst_branch *mstb, | 1013 | struct drm_dp_mst_branch *mstb, |
1014 | char *proppath) | 1014 | char *proppath, |
1015 | size_t proppath_size) | ||
1015 | { | 1016 | { |
1016 | int i; | 1017 | int i; |
1017 | char temp[8]; | 1018 | char temp[8]; |
1018 | snprintf(proppath, 255, "mst:%d", mstb->mgr->conn_base_id); | 1019 | snprintf(proppath, proppath_size, "mst:%d", mstb->mgr->conn_base_id); |
1019 | for (i = 0; i < (mstb->lct - 1); i++) { | 1020 | for (i = 0; i < (mstb->lct - 1); i++) { |
1020 | int shift = (i % 2) ? 0 : 4; | 1021 | int shift = (i % 2) ? 0 : 4; |
1021 | int port_num = mstb->rad[i / 2] >> shift; | 1022 | int port_num = mstb->rad[i / 2] >> shift; |
1022 | snprintf(temp, 8, "-%d", port_num); | 1023 | snprintf(temp, sizeof(temp), "-%d", port_num); |
1023 | strncat(proppath, temp, 255); | 1024 | strlcat(proppath, temp, proppath_size); |
1024 | } | 1025 | } |
1025 | snprintf(temp, 8, "-%d", port->port_num); | 1026 | snprintf(temp, sizeof(temp), "-%d", port->port_num); |
1026 | strncat(proppath, temp, 255); | 1027 | strlcat(proppath, temp, proppath_size); |
1027 | } | 1028 | } |
1028 | 1029 | ||
1029 | static void drm_dp_add_port(struct drm_dp_mst_branch *mstb, | 1030 | static void drm_dp_add_port(struct drm_dp_mst_branch *mstb, |
@@ -1094,7 +1095,7 @@ static void drm_dp_add_port(struct drm_dp_mst_branch *mstb, | |||
1094 | 1095 | ||
1095 | if (created && !port->input) { | 1096 | if (created && !port->input) { |
1096 | char proppath[255]; | 1097 | char proppath[255]; |
1097 | build_mst_prop_path(port, mstb, proppath); | 1098 | build_mst_prop_path(port, mstb, proppath, sizeof(proppath)); |
1098 | port->connector = (*mstb->mgr->cbs->add_connector)(mstb->mgr, port, proppath); | 1099 | port->connector = (*mstb->mgr->cbs->add_connector)(mstb->mgr, port, proppath); |
1099 | } | 1100 | } |
1100 | 1101 | ||
diff --git a/drivers/gpu/drm/drm_drv.c b/drivers/gpu/drm/drm_drv.c index bc3da32d4585..2e5c7d941313 100644 --- a/drivers/gpu/drm/drm_drv.c +++ b/drivers/gpu/drm/drm_drv.c | |||
@@ -56,7 +56,7 @@ static struct idr drm_minors_idr; | |||
56 | struct class *drm_class; | 56 | struct class *drm_class; |
57 | static struct dentry *drm_debugfs_root; | 57 | static struct dentry *drm_debugfs_root; |
58 | 58 | ||
59 | void drm_err(const char *func, const char *format, ...) | 59 | void drm_err(const char *format, ...) |
60 | { | 60 | { |
61 | struct va_format vaf; | 61 | struct va_format vaf; |
62 | va_list args; | 62 | va_list args; |
@@ -66,7 +66,8 @@ void drm_err(const char *func, const char *format, ...) | |||
66 | vaf.fmt = format; | 66 | vaf.fmt = format; |
67 | vaf.va = &args; | 67 | vaf.va = &args; |
68 | 68 | ||
69 | printk(KERN_ERR "[" DRM_NAME ":%s] *ERROR* %pV", func, &vaf); | 69 | printk(KERN_ERR "[" DRM_NAME ":%pf] *ERROR* %pV", |
70 | __builtin_return_address(0), &vaf); | ||
70 | 71 | ||
71 | va_end(args); | 72 | va_end(args); |
72 | } | 73 | } |
diff --git a/drivers/gpu/drm/drm_fb_helper.c b/drivers/gpu/drm/drm_fb_helper.c index 0c0c39bac23d..09d47e9ba026 100644 --- a/drivers/gpu/drm/drm_fb_helper.c +++ b/drivers/gpu/drm/drm_fb_helper.c | |||
@@ -1570,7 +1570,6 @@ static void drm_setup_crtcs(struct drm_fb_helper *fb_helper) | |||
1570 | modeset = &fb_helper->crtc_info[i].mode_set; | 1570 | modeset = &fb_helper->crtc_info[i].mode_set; |
1571 | if (modeset->num_connectors == 0) { | 1571 | if (modeset->num_connectors == 0) { |
1572 | BUG_ON(modeset->fb); | 1572 | BUG_ON(modeset->fb); |
1573 | BUG_ON(modeset->num_connectors); | ||
1574 | if (modeset->mode) | 1573 | if (modeset->mode) |
1575 | drm_mode_destroy(dev, modeset->mode); | 1574 | drm_mode_destroy(dev, modeset->mode); |
1576 | modeset->mode = NULL; | 1575 | modeset->mode = NULL; |
diff --git a/drivers/gpu/drm/drm_fops.c b/drivers/gpu/drm/drm_fops.c index ed7bc68f7e87..91e1105f2800 100644 --- a/drivers/gpu/drm/drm_fops.c +++ b/drivers/gpu/drm/drm_fops.c | |||
@@ -515,10 +515,12 @@ ssize_t drm_read(struct file *filp, char __user *buffer, | |||
515 | size_t total; | 515 | size_t total; |
516 | ssize_t ret; | 516 | ssize_t ret; |
517 | 517 | ||
518 | ret = wait_event_interruptible(file_priv->event_wait, | 518 | if ((filp->f_flags & O_NONBLOCK) == 0) { |
519 | !list_empty(&file_priv->event_list)); | 519 | ret = wait_event_interruptible(file_priv->event_wait, |
520 | if (ret < 0) | 520 | !list_empty(&file_priv->event_list)); |
521 | return ret; | 521 | if (ret < 0) |
522 | return ret; | ||
523 | } | ||
522 | 524 | ||
523 | total = 0; | 525 | total = 0; |
524 | while (drm_dequeue_event(file_priv, total, count, &e)) { | 526 | while (drm_dequeue_event(file_priv, total, count, &e)) { |
@@ -532,7 +534,7 @@ ssize_t drm_read(struct file *filp, char __user *buffer, | |||
532 | e->destroy(e); | 534 | e->destroy(e); |
533 | } | 535 | } |
534 | 536 | ||
535 | return total; | 537 | return total ?: -EAGAIN; |
536 | } | 538 | } |
537 | EXPORT_SYMBOL(drm_read); | 539 | EXPORT_SYMBOL(drm_read); |
538 | 540 | ||
diff --git a/drivers/gpu/drm/drm_irq.c b/drivers/gpu/drm/drm_irq.c index 5ef03c216a27..3e6b582f60dd 100644 --- a/drivers/gpu/drm/drm_irq.c +++ b/drivers/gpu/drm/drm_irq.c | |||
@@ -1190,7 +1190,7 @@ EXPORT_SYMBOL(drm_crtc_vblank_off); | |||
1190 | * | 1190 | * |
1191 | * This functions restores the vblank interrupt state captured with | 1191 | * This functions restores the vblank interrupt state captured with |
1192 | * drm_vblank_off() again. Note that calls to drm_vblank_on() and | 1192 | * drm_vblank_off() again. Note that calls to drm_vblank_on() and |
1193 | * drm_vblank_off() can be unbalanced and so can also be unconditionaly called | 1193 | * drm_vblank_off() can be unbalanced and so can also be unconditionally called |
1194 | * in driver load code to reflect the current hardware state of the crtc. | 1194 | * in driver load code to reflect the current hardware state of the crtc. |
1195 | * | 1195 | * |
1196 | * This is the legacy version of drm_crtc_vblank_on(). | 1196 | * This is the legacy version of drm_crtc_vblank_on(). |
@@ -1237,7 +1237,7 @@ EXPORT_SYMBOL(drm_vblank_on); | |||
1237 | * | 1237 | * |
1238 | * This functions restores the vblank interrupt state captured with | 1238 | * This functions restores the vblank interrupt state captured with |
1239 | * drm_vblank_off() again. Note that calls to drm_vblank_on() and | 1239 | * drm_vblank_off() again. Note that calls to drm_vblank_on() and |
1240 | * drm_vblank_off() can be unbalanced and so can also be unconditionaly called | 1240 | * drm_vblank_off() can be unbalanced and so can also be unconditionally called |
1241 | * in driver load code to reflect the current hardware state of the crtc. | 1241 | * in driver load code to reflect the current hardware state of the crtc. |
1242 | * | 1242 | * |
1243 | * This is the native kms version of drm_vblank_on(). | 1243 | * This is the native kms version of drm_vblank_on(). |
diff --git a/drivers/gpu/drm/drm_modes.c b/drivers/gpu/drm/drm_modes.c index d1b7d2006529..6d8b941c8200 100644 --- a/drivers/gpu/drm/drm_modes.c +++ b/drivers/gpu/drm/drm_modes.c | |||
@@ -914,7 +914,7 @@ EXPORT_SYMBOL(drm_mode_equal_no_clocks_no_stereo); | |||
914 | * | 914 | * |
915 | * This function is a helper which can be used to validate modes against size | 915 | * This function is a helper which can be used to validate modes against size |
916 | * limitations of the DRM device/connector. If a mode is too big its status | 916 | * limitations of the DRM device/connector. If a mode is too big its status |
917 | * memeber is updated with the appropriate validation failure code. The list | 917 | * member is updated with the appropriate validation failure code. The list |
918 | * itself is not changed. | 918 | * itself is not changed. |
919 | */ | 919 | */ |
920 | void drm_mode_validate_size(struct drm_device *dev, | 920 | void drm_mode_validate_size(struct drm_device *dev, |
diff --git a/drivers/gpu/drm/drm_plane_helper.c b/drivers/gpu/drm/drm_plane_helper.c index fe4d1fb2376c..93c6533c25da 100644 --- a/drivers/gpu/drm/drm_plane_helper.c +++ b/drivers/gpu/drm/drm_plane_helper.c | |||
@@ -27,10 +27,38 @@ | |||
27 | #include <drm/drmP.h> | 27 | #include <drm/drmP.h> |
28 | #include <drm/drm_plane_helper.h> | 28 | #include <drm/drm_plane_helper.h> |
29 | #include <drm/drm_rect.h> | 29 | #include <drm/drm_rect.h> |
30 | #include <drm/drm_plane_helper.h> | 30 | #include <drm/drm_atomic.h> |
31 | #include <drm/drm_crtc_helper.h> | ||
32 | #include <drm/drm_atomic_helper.h> | ||
31 | 33 | ||
32 | #define SUBPIXEL_MASK 0xffff | 34 | #define SUBPIXEL_MASK 0xffff |
33 | 35 | ||
36 | /** | ||
37 | * DOC: overview | ||
38 | * | ||
39 | * This helper library has two parts. The first part has support to implement | ||
40 | * primary plane support on top of the normal CRTC configuration interface. | ||
41 | * Since the legacy ->set_config interface ties the primary plane together with | ||
42 | * the CRTC state this does not allow userspace to disable the primary plane | ||
43 | * itself. To avoid too much duplicated code use | ||
44 | * drm_plane_helper_check_update() which can be used to enforce the same | ||
45 | * restrictions as primary planes had thus. The default primary plane only | ||
46 | * expose XRBG8888 and ARGB8888 as valid pixel formats for the attached | ||
47 | * framebuffer. | ||
48 | * | ||
49 | * Drivers are highly recommended to implement proper support for primary | ||
50 | * planes, and newly merged drivers must not rely upon these transitional | ||
51 | * helpers. | ||
52 | * | ||
53 | * The second part also implements transitional helpers which allow drivers to | ||
54 | * gradually switch to the atomic helper infrastructure for plane updates. Once | ||
55 | * that switch is complete drivers shouldn't use these any longer, instead using | ||
56 | * the proper legacy implementations for update and disable plane hooks provided | ||
57 | * by the atomic helpers. | ||
58 | * | ||
59 | * Again drivers are strongly urged to switch to the new interfaces. | ||
60 | */ | ||
61 | |||
34 | /* | 62 | /* |
35 | * This is the minimal list of formats that seem to be safe for modeset use | 63 | * This is the minimal list of formats that seem to be safe for modeset use |
36 | * with all current DRM drivers. Most hardware can actually support more | 64 | * with all current DRM drivers. Most hardware can actually support more |
@@ -374,3 +402,171 @@ int drm_crtc_init(struct drm_device *dev, struct drm_crtc *crtc, | |||
374 | return drm_crtc_init_with_planes(dev, crtc, primary, NULL, funcs); | 402 | return drm_crtc_init_with_planes(dev, crtc, primary, NULL, funcs); |
375 | } | 403 | } |
376 | EXPORT_SYMBOL(drm_crtc_init); | 404 | EXPORT_SYMBOL(drm_crtc_init); |
405 | |||
406 | int drm_plane_helper_commit(struct drm_plane *plane, | ||
407 | struct drm_plane_state *plane_state, | ||
408 | struct drm_framebuffer *old_fb) | ||
409 | { | ||
410 | struct drm_plane_helper_funcs *plane_funcs; | ||
411 | struct drm_crtc *crtc[2]; | ||
412 | struct drm_crtc_helper_funcs *crtc_funcs[2]; | ||
413 | int i, ret = 0; | ||
414 | |||
415 | plane_funcs = plane->helper_private; | ||
416 | |||
417 | /* Since this is a transitional helper we can't assume that plane->state | ||
418 | * is always valid. Hence we need to use plane->crtc instead of | ||
419 | * plane->state->crtc as the old crtc. */ | ||
420 | crtc[0] = plane->crtc; | ||
421 | crtc[1] = crtc[0] != plane_state->crtc ? plane_state->crtc : NULL; | ||
422 | |||
423 | for (i = 0; i < 2; i++) | ||
424 | crtc_funcs[i] = crtc[i] ? crtc[i]->helper_private : NULL; | ||
425 | |||
426 | if (plane_funcs->atomic_check) { | ||
427 | ret = plane_funcs->atomic_check(plane, plane_state); | ||
428 | if (ret) | ||
429 | goto out; | ||
430 | } | ||
431 | |||
432 | if (plane_funcs->prepare_fb && plane_state->fb) { | ||
433 | ret = plane_funcs->prepare_fb(plane, plane_state->fb); | ||
434 | if (ret) | ||
435 | goto out; | ||
436 | } | ||
437 | |||
438 | /* Point of no return, commit sw state. */ | ||
439 | swap(plane->state, plane_state); | ||
440 | |||
441 | for (i = 0; i < 2; i++) { | ||
442 | if (crtc_funcs[i] && crtc_funcs[i]->atomic_begin) | ||
443 | crtc_funcs[i]->atomic_begin(crtc[i]); | ||
444 | } | ||
445 | |||
446 | plane_funcs->atomic_update(plane); | ||
447 | |||
448 | for (i = 0; i < 2; i++) { | ||
449 | if (crtc_funcs[i] && crtc_funcs[i]->atomic_flush) | ||
450 | crtc_funcs[i]->atomic_flush(crtc[i]); | ||
451 | } | ||
452 | |||
453 | for (i = 0; i < 2; i++) { | ||
454 | if (!crtc[i]) | ||
455 | continue; | ||
456 | |||
457 | /* There's no other way to figure out whether the crtc is running. */ | ||
458 | ret = drm_crtc_vblank_get(crtc[i]); | ||
459 | if (ret == 0) { | ||
460 | drm_crtc_wait_one_vblank(crtc[i]); | ||
461 | drm_crtc_vblank_put(crtc[i]); | ||
462 | } | ||
463 | |||
464 | ret = 0; | ||
465 | } | ||
466 | |||
467 | if (plane_funcs->cleanup_fb && old_fb) | ||
468 | plane_funcs->cleanup_fb(plane, old_fb); | ||
469 | out: | ||
470 | if (plane_state) { | ||
471 | if (plane->funcs->atomic_destroy_state) | ||
472 | plane->funcs->atomic_destroy_state(plane, plane_state); | ||
473 | else | ||
474 | drm_atomic_helper_plane_destroy_state(plane, plane_state); | ||
475 | } | ||
476 | |||
477 | return ret; | ||
478 | } | ||
479 | |||
480 | /** | ||
481 | * drm_plane_helper_update() - Helper for primary plane update | ||
482 | * @plane: plane object to update | ||
483 | * @crtc: owning CRTC of owning plane | ||
484 | * @fb: framebuffer to flip onto plane | ||
485 | * @crtc_x: x offset of primary plane on crtc | ||
486 | * @crtc_y: y offset of primary plane on crtc | ||
487 | * @crtc_w: width of primary plane rectangle on crtc | ||
488 | * @crtc_h: height of primary plane rectangle on crtc | ||
489 | * @src_x: x offset of @fb for panning | ||
490 | * @src_y: y offset of @fb for panning | ||
491 | * @src_w: width of source rectangle in @fb | ||
492 | * @src_h: height of source rectangle in @fb | ||
493 | * | ||
494 | * Provides a default plane update handler using the atomic plane update | ||
495 | * functions. It is fully left to the driver to check plane constraints and | ||
496 | * handle corner-cases like a fully occluded or otherwise invisible plane. | ||
497 | * | ||
498 | * This is useful for piecewise transitioning of a driver to the atomic helpers. | ||
499 | * | ||
500 | * RETURNS: | ||
501 | * Zero on success, error code on failure | ||
502 | */ | ||
503 | int drm_plane_helper_update(struct drm_plane *plane, struct drm_crtc *crtc, | ||
504 | struct drm_framebuffer *fb, | ||
505 | int crtc_x, int crtc_y, | ||
506 | unsigned int crtc_w, unsigned int crtc_h, | ||
507 | uint32_t src_x, uint32_t src_y, | ||
508 | uint32_t src_w, uint32_t src_h) | ||
509 | { | ||
510 | struct drm_plane_state *plane_state; | ||
511 | |||
512 | if (plane->funcs->atomic_duplicate_state) | ||
513 | plane_state = plane->funcs->atomic_duplicate_state(plane); | ||
514 | else if (plane->state) | ||
515 | plane_state = drm_atomic_helper_plane_duplicate_state(plane); | ||
516 | else | ||
517 | plane_state = kzalloc(sizeof(*plane_state), GFP_KERNEL); | ||
518 | if (!plane_state) | ||
519 | return -ENOMEM; | ||
520 | |||
521 | plane_state->crtc = crtc; | ||
522 | drm_atomic_set_fb_for_plane(plane_state, fb); | ||
523 | plane_state->crtc_x = crtc_x; | ||
524 | plane_state->crtc_y = crtc_y; | ||
525 | plane_state->crtc_h = crtc_h; | ||
526 | plane_state->crtc_w = crtc_w; | ||
527 | plane_state->src_x = src_x; | ||
528 | plane_state->src_y = src_y; | ||
529 | plane_state->src_h = src_h; | ||
530 | plane_state->src_w = src_w; | ||
531 | |||
532 | return drm_plane_helper_commit(plane, plane_state, plane->fb); | ||
533 | } | ||
534 | EXPORT_SYMBOL(drm_plane_helper_update); | ||
535 | |||
536 | /** | ||
537 | * drm_plane_helper_disable() - Helper for primary plane disable | ||
538 | * @plane: plane to disable | ||
539 | * | ||
540 | * Provides a default plane disable handler using the atomic plane update | ||
541 | * functions. It is fully left to the driver to check plane constraints and | ||
542 | * handle corner-cases like a fully occluded or otherwise invisible plane. | ||
543 | * | ||
544 | * This is useful for piecewise transitioning of a driver to the atomic helpers. | ||
545 | * | ||
546 | * RETURNS: | ||
547 | * Zero on success, error code on failure | ||
548 | */ | ||
549 | int drm_plane_helper_disable(struct drm_plane *plane) | ||
550 | { | ||
551 | struct drm_plane_state *plane_state; | ||
552 | |||
553 | /* crtc helpers love to call disable functions for already disabled hw | ||
554 | * functions. So cope with that. */ | ||
555 | if (!plane->crtc) | ||
556 | return 0; | ||
557 | |||
558 | if (plane->funcs->atomic_duplicate_state) | ||
559 | plane_state = plane->funcs->atomic_duplicate_state(plane); | ||
560 | else if (plane->state) | ||
561 | plane_state = drm_atomic_helper_plane_duplicate_state(plane); | ||
562 | else | ||
563 | plane_state = kzalloc(sizeof(*plane_state), GFP_KERNEL); | ||
564 | if (!plane_state) | ||
565 | return -ENOMEM; | ||
566 | |||
567 | plane_state->crtc = NULL; | ||
568 | drm_atomic_set_fb_for_plane(plane_state, NULL); | ||
569 | |||
570 | return drm_plane_helper_commit(plane, plane_state, plane->fb); | ||
571 | } | ||
572 | EXPORT_SYMBOL(drm_plane_helper_disable); | ||
diff --git a/drivers/gpu/drm/drm_prime.c b/drivers/gpu/drm/drm_prime.c index 78ca30808422..6872eca6555e 100644 --- a/drivers/gpu/drm/drm_prime.c +++ b/drivers/gpu/drm/drm_prime.c | |||
@@ -328,7 +328,7 @@ static const struct dma_buf_ops drm_gem_prime_dmabuf_ops = { | |||
328 | */ | 328 | */ |
329 | 329 | ||
330 | /** | 330 | /** |
331 | * drm_gem_prime_export - helper library implemention of the export callback | 331 | * drm_gem_prime_export - helper library implementation of the export callback |
332 | * @dev: drm_device to export from | 332 | * @dev: drm_device to export from |
333 | * @obj: GEM object to export | 333 | * @obj: GEM object to export |
334 | * @flags: flags like DRM_CLOEXEC | 334 | * @flags: flags like DRM_CLOEXEC |
@@ -483,7 +483,7 @@ out_unlock: | |||
483 | EXPORT_SYMBOL(drm_gem_prime_handle_to_fd); | 483 | EXPORT_SYMBOL(drm_gem_prime_handle_to_fd); |
484 | 484 | ||
485 | /** | 485 | /** |
486 | * drm_gem_prime_import - helper library implemention of the import callback | 486 | * drm_gem_prime_import - helper library implementation of the import callback |
487 | * @dev: drm_device to import into | 487 | * @dev: drm_device to import into |
488 | * @dma_buf: dma-buf object to import | 488 | * @dma_buf: dma-buf object to import |
489 | * | 489 | * |
diff --git a/drivers/gpu/drm/drm_probe_helper.c b/drivers/gpu/drm/drm_probe_helper.c index 6857e9ad6339..7483a47de8e4 100644 --- a/drivers/gpu/drm/drm_probe_helper.c +++ b/drivers/gpu/drm/drm_probe_helper.c | |||
@@ -118,7 +118,8 @@ static int drm_helper_probe_single_connector_modes_merge_bits(struct drm_connect | |||
118 | mode->status = MODE_UNVERIFIED; | 118 | mode->status = MODE_UNVERIFIED; |
119 | 119 | ||
120 | if (connector->force) { | 120 | if (connector->force) { |
121 | if (connector->force == DRM_FORCE_ON) | 121 | if (connector->force == DRM_FORCE_ON || |
122 | connector->force == DRM_FORCE_ON_DIGITAL) | ||
122 | connector->status = connector_status_connected; | 123 | connector->status = connector_status_connected; |
123 | else | 124 | else |
124 | connector->status = connector_status_disconnected; | 125 | connector->status = connector_status_disconnected; |
diff --git a/drivers/gpu/drm/gma500/cdv_intel_dp.c b/drivers/gpu/drm/gma500/cdv_intel_dp.c index 9f158eab517a..0fafb8e2483a 100644 --- a/drivers/gpu/drm/gma500/cdv_intel_dp.c +++ b/drivers/gpu/drm/gma500/cdv_intel_dp.c | |||
@@ -37,6 +37,201 @@ | |||
37 | #include "gma_display.h" | 37 | #include "gma_display.h" |
38 | #include <drm/drm_dp_helper.h> | 38 | #include <drm/drm_dp_helper.h> |
39 | 39 | ||
40 | /** | ||
41 | * struct i2c_algo_dp_aux_data - driver interface structure for i2c over dp | ||
42 | * aux algorithm | ||
43 | * @running: set by the algo indicating whether an i2c is ongoing or whether | ||
44 | * the i2c bus is quiescent | ||
45 | * @address: i2c target address for the currently ongoing transfer | ||
46 | * @aux_ch: driver callback to transfer a single byte of the i2c payload | ||
47 | */ | ||
48 | struct i2c_algo_dp_aux_data { | ||
49 | bool running; | ||
50 | u16 address; | ||
51 | int (*aux_ch) (struct i2c_adapter *adapter, | ||
52 | int mode, uint8_t write_byte, | ||
53 | uint8_t *read_byte); | ||
54 | }; | ||
55 | |||
56 | /* Run a single AUX_CH I2C transaction, writing/reading data as necessary */ | ||
57 | static int | ||
58 | i2c_algo_dp_aux_transaction(struct i2c_adapter *adapter, int mode, | ||
59 | uint8_t write_byte, uint8_t *read_byte) | ||
60 | { | ||
61 | struct i2c_algo_dp_aux_data *algo_data = adapter->algo_data; | ||
62 | int ret; | ||
63 | |||
64 | ret = (*algo_data->aux_ch)(adapter, mode, | ||
65 | write_byte, read_byte); | ||
66 | return ret; | ||
67 | } | ||
68 | |||
69 | /* | ||
70 | * I2C over AUX CH | ||
71 | */ | ||
72 | |||
73 | /* | ||
74 | * Send the address. If the I2C link is running, this 'restarts' | ||
75 | * the connection with the new address, this is used for doing | ||
76 | * a write followed by a read (as needed for DDC) | ||
77 | */ | ||
78 | static int | ||
79 | i2c_algo_dp_aux_address(struct i2c_adapter *adapter, u16 address, bool reading) | ||
80 | { | ||
81 | struct i2c_algo_dp_aux_data *algo_data = adapter->algo_data; | ||
82 | int mode = MODE_I2C_START; | ||
83 | int ret; | ||
84 | |||
85 | if (reading) | ||
86 | mode |= MODE_I2C_READ; | ||
87 | else | ||
88 | mode |= MODE_I2C_WRITE; | ||
89 | algo_data->address = address; | ||
90 | algo_data->running = true; | ||
91 | ret = i2c_algo_dp_aux_transaction(adapter, mode, 0, NULL); | ||
92 | return ret; | ||
93 | } | ||
94 | |||
95 | /* | ||
96 | * Stop the I2C transaction. This closes out the link, sending | ||
97 | * a bare address packet with the MOT bit turned off | ||
98 | */ | ||
99 | static void | ||
100 | i2c_algo_dp_aux_stop(struct i2c_adapter *adapter, bool reading) | ||
101 | { | ||
102 | struct i2c_algo_dp_aux_data *algo_data = adapter->algo_data; | ||
103 | int mode = MODE_I2C_STOP; | ||
104 | |||
105 | if (reading) | ||
106 | mode |= MODE_I2C_READ; | ||
107 | else | ||
108 | mode |= MODE_I2C_WRITE; | ||
109 | if (algo_data->running) { | ||
110 | (void) i2c_algo_dp_aux_transaction(adapter, mode, 0, NULL); | ||
111 | algo_data->running = false; | ||
112 | } | ||
113 | } | ||
114 | |||
115 | /* | ||
116 | * Write a single byte to the current I2C address, the | ||
117 | * the I2C link must be running or this returns -EIO | ||
118 | */ | ||
119 | static int | ||
120 | i2c_algo_dp_aux_put_byte(struct i2c_adapter *adapter, u8 byte) | ||
121 | { | ||
122 | struct i2c_algo_dp_aux_data *algo_data = adapter->algo_data; | ||
123 | int ret; | ||
124 | |||
125 | if (!algo_data->running) | ||
126 | return -EIO; | ||
127 | |||
128 | ret = i2c_algo_dp_aux_transaction(adapter, MODE_I2C_WRITE, byte, NULL); | ||
129 | return ret; | ||
130 | } | ||
131 | |||
132 | /* | ||
133 | * Read a single byte from the current I2C address, the | ||
134 | * I2C link must be running or this returns -EIO | ||
135 | */ | ||
136 | static int | ||
137 | i2c_algo_dp_aux_get_byte(struct i2c_adapter *adapter, u8 *byte_ret) | ||
138 | { | ||
139 | struct i2c_algo_dp_aux_data *algo_data = adapter->algo_data; | ||
140 | int ret; | ||
141 | |||
142 | if (!algo_data->running) | ||
143 | return -EIO; | ||
144 | |||
145 | ret = i2c_algo_dp_aux_transaction(adapter, MODE_I2C_READ, 0, byte_ret); | ||
146 | return ret; | ||
147 | } | ||
148 | |||
149 | static int | ||
150 | i2c_algo_dp_aux_xfer(struct i2c_adapter *adapter, | ||
151 | struct i2c_msg *msgs, | ||
152 | int num) | ||
153 | { | ||
154 | int ret = 0; | ||
155 | bool reading = false; | ||
156 | int m; | ||
157 | int b; | ||
158 | |||
159 | for (m = 0; m < num; m++) { | ||
160 | u16 len = msgs[m].len; | ||
161 | u8 *buf = msgs[m].buf; | ||
162 | reading = (msgs[m].flags & I2C_M_RD) != 0; | ||
163 | ret = i2c_algo_dp_aux_address(adapter, msgs[m].addr, reading); | ||
164 | if (ret < 0) | ||
165 | break; | ||
166 | if (reading) { | ||
167 | for (b = 0; b < len; b++) { | ||
168 | ret = i2c_algo_dp_aux_get_byte(adapter, &buf[b]); | ||
169 | if (ret < 0) | ||
170 | break; | ||
171 | } | ||
172 | } else { | ||
173 | for (b = 0; b < len; b++) { | ||
174 | ret = i2c_algo_dp_aux_put_byte(adapter, buf[b]); | ||
175 | if (ret < 0) | ||
176 | break; | ||
177 | } | ||
178 | } | ||
179 | if (ret < 0) | ||
180 | break; | ||
181 | } | ||
182 | if (ret >= 0) | ||
183 | ret = num; | ||
184 | i2c_algo_dp_aux_stop(adapter, reading); | ||
185 | DRM_DEBUG_KMS("dp_aux_xfer return %d\n", ret); | ||
186 | return ret; | ||
187 | } | ||
188 | |||
189 | static u32 | ||
190 | i2c_algo_dp_aux_functionality(struct i2c_adapter *adapter) | ||
191 | { | ||
192 | return I2C_FUNC_I2C | I2C_FUNC_SMBUS_EMUL | | ||
193 | I2C_FUNC_SMBUS_READ_BLOCK_DATA | | ||
194 | I2C_FUNC_SMBUS_BLOCK_PROC_CALL | | ||
195 | I2C_FUNC_10BIT_ADDR; | ||
196 | } | ||
197 | |||
198 | static const struct i2c_algorithm i2c_dp_aux_algo = { | ||
199 | .master_xfer = i2c_algo_dp_aux_xfer, | ||
200 | .functionality = i2c_algo_dp_aux_functionality, | ||
201 | }; | ||
202 | |||
203 | static void | ||
204 | i2c_dp_aux_reset_bus(struct i2c_adapter *adapter) | ||
205 | { | ||
206 | (void) i2c_algo_dp_aux_address(adapter, 0, false); | ||
207 | (void) i2c_algo_dp_aux_stop(adapter, false); | ||
208 | } | ||
209 | |||
210 | static int | ||
211 | i2c_dp_aux_prepare_bus(struct i2c_adapter *adapter) | ||
212 | { | ||
213 | adapter->algo = &i2c_dp_aux_algo; | ||
214 | adapter->retries = 3; | ||
215 | i2c_dp_aux_reset_bus(adapter); | ||
216 | return 0; | ||
217 | } | ||
218 | |||
219 | /* | ||
220 | * FIXME: This is the old dp aux helper, gma500 is the last driver that needs to | ||
221 | * be ported over to the new helper code in drm_dp_helper.c like i915 or radeon. | ||
222 | */ | ||
223 | static int __deprecated | ||
224 | i2c_dp_aux_add_bus(struct i2c_adapter *adapter) | ||
225 | { | ||
226 | int error; | ||
227 | |||
228 | error = i2c_dp_aux_prepare_bus(adapter); | ||
229 | if (error) | ||
230 | return error; | ||
231 | error = i2c_add_adapter(adapter); | ||
232 | return error; | ||
233 | } | ||
234 | |||
40 | #define _wait_for(COND, MS, W) ({ \ | 235 | #define _wait_for(COND, MS, W) ({ \ |
41 | unsigned long timeout__ = jiffies + msecs_to_jiffies(MS); \ | 236 | unsigned long timeout__ = jiffies + msecs_to_jiffies(MS); \ |
42 | int ret__ = 0; \ | 237 | int ret__ = 0; \ |
diff --git a/drivers/gpu/drm/gma500/psb_intel_display.c b/drivers/gpu/drm/gma500/psb_intel_display.c index 87b50ba64ed4..b21a09451d1d 100644 --- a/drivers/gpu/drm/gma500/psb_intel_display.c +++ b/drivers/gpu/drm/gma500/psb_intel_display.c | |||
@@ -21,6 +21,7 @@ | |||
21 | #include <linux/i2c.h> | 21 | #include <linux/i2c.h> |
22 | 22 | ||
23 | #include <drm/drmP.h> | 23 | #include <drm/drmP.h> |
24 | #include <drm/drm_plane_helper.h> | ||
24 | #include "framebuffer.h" | 25 | #include "framebuffer.h" |
25 | #include "psb_drv.h" | 26 | #include "psb_drv.h" |
26 | #include "psb_intel_drv.h" | 27 | #include "psb_intel_drv.h" |
diff --git a/drivers/gpu/drm/gma500/psb_intel_sdvo.c b/drivers/gpu/drm/gma500/psb_intel_sdvo.c index 0be96fdb5e28..58529cea575d 100644 --- a/drivers/gpu/drm/gma500/psb_intel_sdvo.c +++ b/drivers/gpu/drm/gma500/psb_intel_sdvo.c | |||
@@ -1631,57 +1631,8 @@ static int psb_intel_sdvo_get_modes(struct drm_connector *connector) | |||
1631 | return !list_empty(&connector->probed_modes); | 1631 | return !list_empty(&connector->probed_modes); |
1632 | } | 1632 | } |
1633 | 1633 | ||
1634 | static void | ||
1635 | psb_intel_sdvo_destroy_enhance_property(struct drm_connector *connector) | ||
1636 | { | ||
1637 | struct psb_intel_sdvo_connector *psb_intel_sdvo_connector = to_psb_intel_sdvo_connector(connector); | ||
1638 | struct drm_device *dev = connector->dev; | ||
1639 | |||
1640 | if (psb_intel_sdvo_connector->left) | ||
1641 | drm_property_destroy(dev, psb_intel_sdvo_connector->left); | ||
1642 | if (psb_intel_sdvo_connector->right) | ||
1643 | drm_property_destroy(dev, psb_intel_sdvo_connector->right); | ||
1644 | if (psb_intel_sdvo_connector->top) | ||
1645 | drm_property_destroy(dev, psb_intel_sdvo_connector->top); | ||
1646 | if (psb_intel_sdvo_connector->bottom) | ||
1647 | drm_property_destroy(dev, psb_intel_sdvo_connector->bottom); | ||
1648 | if (psb_intel_sdvo_connector->hpos) | ||
1649 | drm_property_destroy(dev, psb_intel_sdvo_connector->hpos); | ||
1650 | if (psb_intel_sdvo_connector->vpos) | ||
1651 | drm_property_destroy(dev, psb_intel_sdvo_connector->vpos); | ||
1652 | if (psb_intel_sdvo_connector->saturation) | ||
1653 | drm_property_destroy(dev, psb_intel_sdvo_connector->saturation); | ||
1654 | if (psb_intel_sdvo_connector->contrast) | ||
1655 | drm_property_destroy(dev, psb_intel_sdvo_connector->contrast); | ||
1656 | if (psb_intel_sdvo_connector->hue) | ||
1657 | drm_property_destroy(dev, psb_intel_sdvo_connector->hue); | ||
1658 | if (psb_intel_sdvo_connector->sharpness) | ||
1659 | drm_property_destroy(dev, psb_intel_sdvo_connector->sharpness); | ||
1660 | if (psb_intel_sdvo_connector->flicker_filter) | ||
1661 | drm_property_destroy(dev, psb_intel_sdvo_connector->flicker_filter); | ||
1662 | if (psb_intel_sdvo_connector->flicker_filter_2d) | ||
1663 | drm_property_destroy(dev, psb_intel_sdvo_connector->flicker_filter_2d); | ||
1664 | if (psb_intel_sdvo_connector->flicker_filter_adaptive) | ||
1665 | drm_property_destroy(dev, psb_intel_sdvo_connector->flicker_filter_adaptive); | ||
1666 | if (psb_intel_sdvo_connector->tv_luma_filter) | ||
1667 | drm_property_destroy(dev, psb_intel_sdvo_connector->tv_luma_filter); | ||
1668 | if (psb_intel_sdvo_connector->tv_chroma_filter) | ||
1669 | drm_property_destroy(dev, psb_intel_sdvo_connector->tv_chroma_filter); | ||
1670 | if (psb_intel_sdvo_connector->dot_crawl) | ||
1671 | drm_property_destroy(dev, psb_intel_sdvo_connector->dot_crawl); | ||
1672 | if (psb_intel_sdvo_connector->brightness) | ||
1673 | drm_property_destroy(dev, psb_intel_sdvo_connector->brightness); | ||
1674 | } | ||
1675 | |||
1676 | static void psb_intel_sdvo_destroy(struct drm_connector *connector) | 1634 | static void psb_intel_sdvo_destroy(struct drm_connector *connector) |
1677 | { | 1635 | { |
1678 | struct psb_intel_sdvo_connector *psb_intel_sdvo_connector = to_psb_intel_sdvo_connector(connector); | ||
1679 | |||
1680 | if (psb_intel_sdvo_connector->tv_format) | ||
1681 | drm_property_destroy(connector->dev, | ||
1682 | psb_intel_sdvo_connector->tv_format); | ||
1683 | |||
1684 | psb_intel_sdvo_destroy_enhance_property(connector); | ||
1685 | drm_connector_unregister(connector); | 1636 | drm_connector_unregister(connector); |
1686 | drm_connector_cleanup(connector); | 1637 | drm_connector_cleanup(connector); |
1687 | kfree(connector); | 1638 | kfree(connector); |
diff --git a/drivers/gpu/drm/i915/i915_cmd_parser.c b/drivers/gpu/drm/i915/i915_cmd_parser.c index ef38915075a1..809bb957b452 100644 --- a/drivers/gpu/drm/i915/i915_cmd_parser.c +++ b/drivers/gpu/drm/i915/i915_cmd_parser.c | |||
@@ -73,7 +73,7 @@ | |||
73 | * those commands required by the parser. This generally works because command | 73 | * those commands required by the parser. This generally works because command |
74 | * opcode ranges have standard command length encodings. So for commands that | 74 | * opcode ranges have standard command length encodings. So for commands that |
75 | * the parser does not need to check, it can easily skip them. This is | 75 | * the parser does not need to check, it can easily skip them. This is |
76 | * implementated via a per-ring length decoding vfunc. | 76 | * implemented via a per-ring length decoding vfunc. |
77 | * | 77 | * |
78 | * Unfortunately, there are a number of commands that do not follow the standard | 78 | * Unfortunately, there are a number of commands that do not follow the standard |
79 | * length encoding for their opcode range, primarily amongst the MI_* commands. | 79 | * length encoding for their opcode range, primarily amongst the MI_* commands. |
@@ -843,7 +843,7 @@ finish: | |||
843 | * @ring: the ring in question | 843 | * @ring: the ring in question |
844 | * | 844 | * |
845 | * Only certain platforms require software batch buffer command parsing, and | 845 | * Only certain platforms require software batch buffer command parsing, and |
846 | * only when enabled via module paramter. | 846 | * only when enabled via module parameter. |
847 | * | 847 | * |
848 | * Return: true if the ring requires software command parsing | 848 | * Return: true if the ring requires software command parsing |
849 | */ | 849 | */ |
diff --git a/drivers/gpu/drm/i915/i915_reg.h b/drivers/gpu/drm/i915/i915_reg.h index b250d96ab7a1..d43fa0e627f8 100644 --- a/drivers/gpu/drm/i915/i915_reg.h +++ b/drivers/gpu/drm/i915/i915_reg.h | |||
@@ -672,7 +672,7 @@ enum punit_power_well { | |||
672 | * need to be accessed during AUX communication, | 672 | * need to be accessed during AUX communication, |
673 | * | 673 | * |
674 | * Generally the common lane corresponds to the pipe and | 674 | * Generally the common lane corresponds to the pipe and |
675 | * the spline (PCS/TX) correponds to the port. | 675 | * the spline (PCS/TX) corresponds to the port. |
676 | * | 676 | * |
677 | * For dual channel PHY (VLV/CHV): | 677 | * For dual channel PHY (VLV/CHV): |
678 | * | 678 | * |
diff --git a/drivers/gpu/drm/i915/intel_lrc.c b/drivers/gpu/drm/i915/intel_lrc.c index 292beb0fa1dc..6025ac754c37 100644 --- a/drivers/gpu/drm/i915/intel_lrc.c +++ b/drivers/gpu/drm/i915/intel_lrc.c | |||
@@ -1681,7 +1681,7 @@ static int lrc_setup_hardware_status_page(struct intel_engine_cs *ring, | |||
1681 | * the creation is a deferred call: it's better to make sure first that we need to use | 1681 | * the creation is a deferred call: it's better to make sure first that we need to use |
1682 | * a given ring with the context. | 1682 | * a given ring with the context. |
1683 | * | 1683 | * |
1684 | * Return: non-zero on eror. | 1684 | * Return: non-zero on error. |
1685 | */ | 1685 | */ |
1686 | int intel_lr_context_deferred_create(struct intel_context *ctx, | 1686 | int intel_lr_context_deferred_create(struct intel_context *ctx, |
1687 | struct intel_engine_cs *ring) | 1687 | struct intel_engine_cs *ring) |
diff --git a/drivers/gpu/drm/i915/intel_sdvo.c b/drivers/gpu/drm/i915/intel_sdvo.c index 9350edd6728d..6d7a277458b5 100644 --- a/drivers/gpu/drm/i915/intel_sdvo.c +++ b/drivers/gpu/drm/i915/intel_sdvo.c | |||
@@ -1991,57 +1991,10 @@ static int intel_sdvo_get_modes(struct drm_connector *connector) | |||
1991 | return !list_empty(&connector->probed_modes); | 1991 | return !list_empty(&connector->probed_modes); |
1992 | } | 1992 | } |
1993 | 1993 | ||
1994 | static void | ||
1995 | intel_sdvo_destroy_enhance_property(struct drm_connector *connector) | ||
1996 | { | ||
1997 | struct intel_sdvo_connector *intel_sdvo_connector = to_intel_sdvo_connector(connector); | ||
1998 | struct drm_device *dev = connector->dev; | ||
1999 | |||
2000 | if (intel_sdvo_connector->left) | ||
2001 | drm_property_destroy(dev, intel_sdvo_connector->left); | ||
2002 | if (intel_sdvo_connector->right) | ||
2003 | drm_property_destroy(dev, intel_sdvo_connector->right); | ||
2004 | if (intel_sdvo_connector->top) | ||
2005 | drm_property_destroy(dev, intel_sdvo_connector->top); | ||
2006 | if (intel_sdvo_connector->bottom) | ||
2007 | drm_property_destroy(dev, intel_sdvo_connector->bottom); | ||
2008 | if (intel_sdvo_connector->hpos) | ||
2009 | drm_property_destroy(dev, intel_sdvo_connector->hpos); | ||
2010 | if (intel_sdvo_connector->vpos) | ||
2011 | drm_property_destroy(dev, intel_sdvo_connector->vpos); | ||
2012 | if (intel_sdvo_connector->saturation) | ||
2013 | drm_property_destroy(dev, intel_sdvo_connector->saturation); | ||
2014 | if (intel_sdvo_connector->contrast) | ||
2015 | drm_property_destroy(dev, intel_sdvo_connector->contrast); | ||
2016 | if (intel_sdvo_connector->hue) | ||
2017 | drm_property_destroy(dev, intel_sdvo_connector->hue); | ||
2018 | if (intel_sdvo_connector->sharpness) | ||
2019 | drm_property_destroy(dev, intel_sdvo_connector->sharpness); | ||
2020 | if (intel_sdvo_connector->flicker_filter) | ||
2021 | drm_property_destroy(dev, intel_sdvo_connector->flicker_filter); | ||
2022 | if (intel_sdvo_connector->flicker_filter_2d) | ||
2023 | drm_property_destroy(dev, intel_sdvo_connector->flicker_filter_2d); | ||
2024 | if (intel_sdvo_connector->flicker_filter_adaptive) | ||
2025 | drm_property_destroy(dev, intel_sdvo_connector->flicker_filter_adaptive); | ||
2026 | if (intel_sdvo_connector->tv_luma_filter) | ||
2027 | drm_property_destroy(dev, intel_sdvo_connector->tv_luma_filter); | ||
2028 | if (intel_sdvo_connector->tv_chroma_filter) | ||
2029 | drm_property_destroy(dev, intel_sdvo_connector->tv_chroma_filter); | ||
2030 | if (intel_sdvo_connector->dot_crawl) | ||
2031 | drm_property_destroy(dev, intel_sdvo_connector->dot_crawl); | ||
2032 | if (intel_sdvo_connector->brightness) | ||
2033 | drm_property_destroy(dev, intel_sdvo_connector->brightness); | ||
2034 | } | ||
2035 | |||
2036 | static void intel_sdvo_destroy(struct drm_connector *connector) | 1994 | static void intel_sdvo_destroy(struct drm_connector *connector) |
2037 | { | 1995 | { |
2038 | struct intel_sdvo_connector *intel_sdvo_connector = to_intel_sdvo_connector(connector); | 1996 | struct intel_sdvo_connector *intel_sdvo_connector = to_intel_sdvo_connector(connector); |
2039 | 1997 | ||
2040 | if (intel_sdvo_connector->tv_format) | ||
2041 | drm_property_destroy(connector->dev, | ||
2042 | intel_sdvo_connector->tv_format); | ||
2043 | |||
2044 | intel_sdvo_destroy_enhance_property(connector); | ||
2045 | drm_connector_cleanup(connector); | 1998 | drm_connector_cleanup(connector); |
2046 | kfree(intel_sdvo_connector); | 1999 | kfree(intel_sdvo_connector); |
2047 | } | 2000 | } |
diff --git a/drivers/gpu/drm/mgag200/mgag200_mode.c b/drivers/gpu/drm/mgag200/mgag200_mode.c index 83485ab81ce8..9872ba9abf1a 100644 --- a/drivers/gpu/drm/mgag200/mgag200_mode.c +++ b/drivers/gpu/drm/mgag200/mgag200_mode.c | |||
@@ -15,6 +15,7 @@ | |||
15 | 15 | ||
16 | #include <drm/drmP.h> | 16 | #include <drm/drmP.h> |
17 | #include <drm/drm_crtc_helper.h> | 17 | #include <drm/drm_crtc_helper.h> |
18 | #include <drm/drm_plane_helper.h> | ||
18 | 19 | ||
19 | #include "mgag200_drv.h" | 20 | #include "mgag200_drv.h" |
20 | 21 | ||
diff --git a/drivers/gpu/drm/nouveau/dispnv04/crtc.c b/drivers/gpu/drm/nouveau/dispnv04/crtc.c index fca6a1f9c20c..2a03e77abef4 100644 --- a/drivers/gpu/drm/nouveau/dispnv04/crtc.c +++ b/drivers/gpu/drm/nouveau/dispnv04/crtc.c | |||
@@ -26,6 +26,7 @@ | |||
26 | 26 | ||
27 | #include <drm/drmP.h> | 27 | #include <drm/drmP.h> |
28 | #include <drm/drm_crtc_helper.h> | 28 | #include <drm/drm_crtc_helper.h> |
29 | #include <drm/drm_plane_helper.h> | ||
29 | 30 | ||
30 | #include "nouveau_drm.h" | 31 | #include "nouveau_drm.h" |
31 | #include "nouveau_reg.h" | 32 | #include "nouveau_reg.h" |
diff --git a/drivers/gpu/drm/nouveau/nv50_display.c b/drivers/gpu/drm/nouveau/nv50_display.c index ae873d1a8d46..76b8c4f980ea 100644 --- a/drivers/gpu/drm/nouveau/nv50_display.c +++ b/drivers/gpu/drm/nouveau/nv50_display.c | |||
@@ -26,6 +26,7 @@ | |||
26 | 26 | ||
27 | #include <drm/drmP.h> | 27 | #include <drm/drmP.h> |
28 | #include <drm/drm_crtc_helper.h> | 28 | #include <drm/drm_crtc_helper.h> |
29 | #include <drm/drm_plane_helper.h> | ||
29 | #include <drm/drm_dp_helper.h> | 30 | #include <drm/drm_dp_helper.h> |
30 | 31 | ||
31 | #include <nvif/class.h> | 32 | #include <nvif/class.h> |
diff --git a/drivers/gpu/drm/omapdrm/omap_crtc.c b/drivers/gpu/drm/omapdrm/omap_crtc.c index 2d28dc337cfb..b0566a1ca28f 100644 --- a/drivers/gpu/drm/omapdrm/omap_crtc.c +++ b/drivers/gpu/drm/omapdrm/omap_crtc.c | |||
@@ -20,6 +20,7 @@ | |||
20 | #include "omap_drv.h" | 20 | #include "omap_drv.h" |
21 | 21 | ||
22 | #include <drm/drm_mode.h> | 22 | #include <drm/drm_mode.h> |
23 | #include <drm/drm_plane_helper.h> | ||
23 | #include "drm_crtc.h" | 24 | #include "drm_crtc.h" |
24 | #include "drm_crtc_helper.h" | 25 | #include "drm_crtc_helper.h" |
25 | 26 | ||
diff --git a/drivers/gpu/drm/qxl/qxl_display.c b/drivers/gpu/drm/qxl/qxl_display.c index 0d1396266857..8b7892880ad2 100644 --- a/drivers/gpu/drm/qxl/qxl_display.c +++ b/drivers/gpu/drm/qxl/qxl_display.c | |||
@@ -29,6 +29,7 @@ | |||
29 | #include "qxl_drv.h" | 29 | #include "qxl_drv.h" |
30 | #include "qxl_object.h" | 30 | #include "qxl_object.h" |
31 | #include "drm_crtc_helper.h" | 31 | #include "drm_crtc_helper.h" |
32 | #include <drm/drm_plane_helper.h> | ||
32 | 33 | ||
33 | static bool qxl_head_enabled(struct qxl_head *head) | 34 | static bool qxl_head_enabled(struct qxl_head *head) |
34 | { | 35 | { |
diff --git a/drivers/gpu/drm/radeon/radeon_display.c b/drivers/gpu/drm/radeon/radeon_display.c index 00ead8c2758a..f1b0fa1285bb 100644 --- a/drivers/gpu/drm/radeon/radeon_display.c +++ b/drivers/gpu/drm/radeon/radeon_display.c | |||
@@ -32,6 +32,7 @@ | |||
32 | 32 | ||
33 | #include <linux/pm_runtime.h> | 33 | #include <linux/pm_runtime.h> |
34 | #include <drm/drm_crtc_helper.h> | 34 | #include <drm/drm_crtc_helper.h> |
35 | #include <drm/drm_plane_helper.h> | ||
35 | #include <drm/drm_edid.h> | 36 | #include <drm/drm_edid.h> |
36 | 37 | ||
37 | #include <linux/gcd.h> | 38 | #include <linux/gcd.h> |
diff --git a/drivers/gpu/drm/rcar-du/rcar_du_crtc.c b/drivers/gpu/drm/rcar-du/rcar_du_crtc.c index 148b50589181..088bfd875d29 100644 --- a/drivers/gpu/drm/rcar-du/rcar_du_crtc.c +++ b/drivers/gpu/drm/rcar-du/rcar_du_crtc.c | |||
@@ -19,6 +19,7 @@ | |||
19 | #include <drm/drm_crtc_helper.h> | 19 | #include <drm/drm_crtc_helper.h> |
20 | #include <drm/drm_fb_cma_helper.h> | 20 | #include <drm/drm_fb_cma_helper.h> |
21 | #include <drm/drm_gem_cma_helper.h> | 21 | #include <drm/drm_gem_cma_helper.h> |
22 | #include <drm/drm_plane_helper.h> | ||
22 | 23 | ||
23 | #include "rcar_du_crtc.h" | 24 | #include "rcar_du_crtc.h" |
24 | #include "rcar_du_drv.h" | 25 | #include "rcar_du_drv.h" |
diff --git a/drivers/gpu/drm/shmobile/shmob_drm_crtc.c b/drivers/gpu/drm/shmobile/shmob_drm_crtc.c index 0ddce4d046d9..859ccb658601 100644 --- a/drivers/gpu/drm/shmobile/shmob_drm_crtc.c +++ b/drivers/gpu/drm/shmobile/shmob_drm_crtc.c | |||
@@ -19,6 +19,7 @@ | |||
19 | #include <drm/drm_crtc_helper.h> | 19 | #include <drm/drm_crtc_helper.h> |
20 | #include <drm/drm_fb_cma_helper.h> | 20 | #include <drm/drm_fb_cma_helper.h> |
21 | #include <drm/drm_gem_cma_helper.h> | 21 | #include <drm/drm_gem_cma_helper.h> |
22 | #include <drm/drm_plane_helper.h> | ||
22 | 23 | ||
23 | #include <video/sh_mobile_meram.h> | 24 | #include <video/sh_mobile_meram.h> |
24 | 25 | ||
diff --git a/drivers/gpu/drm/sti/sti_drm_crtc.c b/drivers/gpu/drm/sti/sti_drm_crtc.c index d2ae0c0e13be..36a1ad3c4823 100644 --- a/drivers/gpu/drm/sti/sti_drm_crtc.c +++ b/drivers/gpu/drm/sti/sti_drm_crtc.c | |||
@@ -10,6 +10,7 @@ | |||
10 | 10 | ||
11 | #include <drm/drmP.h> | 11 | #include <drm/drmP.h> |
12 | #include <drm/drm_crtc_helper.h> | 12 | #include <drm/drm_crtc_helper.h> |
13 | #include <drm/drm_plane_helper.h> | ||
13 | 14 | ||
14 | #include "sti_compositor.h" | 15 | #include "sti_compositor.h" |
15 | #include "sti_drm_drv.h" | 16 | #include "sti_drm_drv.h" |
diff --git a/drivers/gpu/drm/tegra/dc.c b/drivers/gpu/drm/tegra/dc.c index 6553fd238685..cdfa126a4725 100644 --- a/drivers/gpu/drm/tegra/dc.c +++ b/drivers/gpu/drm/tegra/dc.c | |||
@@ -15,6 +15,8 @@ | |||
15 | #include "drm.h" | 15 | #include "drm.h" |
16 | #include "gem.h" | 16 | #include "gem.h" |
17 | 17 | ||
18 | #include <drm/drm_plane_helper.h> | ||
19 | |||
18 | struct tegra_dc_soc_info { | 20 | struct tegra_dc_soc_info { |
19 | bool supports_interlacing; | 21 | bool supports_interlacing; |
20 | bool supports_cursor; | 22 | bool supports_cursor; |
diff --git a/drivers/gpu/drm/tilcdc/tilcdc_crtc.c b/drivers/gpu/drm/tilcdc/tilcdc_crtc.c index d642d4a02134..29ec98baffd1 100644 --- a/drivers/gpu/drm/tilcdc/tilcdc_crtc.c +++ b/drivers/gpu/drm/tilcdc/tilcdc_crtc.c | |||
@@ -16,6 +16,7 @@ | |||
16 | */ | 16 | */ |
17 | 17 | ||
18 | #include "drm_flip_work.h" | 18 | #include "drm_flip_work.h" |
19 | #include <drm/drm_plane_helper.h> | ||
19 | 20 | ||
20 | #include "tilcdc_drv.h" | 21 | #include "tilcdc_drv.h" |
21 | #include "tilcdc_regs.h" | 22 | #include "tilcdc_regs.h" |
diff --git a/drivers/gpu/drm/udl/udl_modeset.c b/drivers/gpu/drm/udl/udl_modeset.c index dc145d320b25..1701f1dfb23f 100644 --- a/drivers/gpu/drm/udl/udl_modeset.c +++ b/drivers/gpu/drm/udl/udl_modeset.c | |||
@@ -14,6 +14,7 @@ | |||
14 | #include <drm/drmP.h> | 14 | #include <drm/drmP.h> |
15 | #include <drm/drm_crtc.h> | 15 | #include <drm/drm_crtc.h> |
16 | #include <drm/drm_crtc_helper.h> | 16 | #include <drm/drm_crtc_helper.h> |
17 | #include <drm/drm_plane_helper.h> | ||
17 | #include "udl_drv.h" | 18 | #include "udl_drv.h" |
18 | 19 | ||
19 | /* | 20 | /* |
diff --git a/drivers/gpu/drm/vmwgfx/vmwgfx_ldu.c b/drivers/gpu/drm/vmwgfx/vmwgfx_ldu.c index 15e185ae4c99..5c289f748ab4 100644 --- a/drivers/gpu/drm/vmwgfx/vmwgfx_ldu.c +++ b/drivers/gpu/drm/vmwgfx/vmwgfx_ldu.c | |||
@@ -26,6 +26,7 @@ | |||
26 | **************************************************************************/ | 26 | **************************************************************************/ |
27 | 27 | ||
28 | #include "vmwgfx_kms.h" | 28 | #include "vmwgfx_kms.h" |
29 | #include <drm/drm_plane_helper.h> | ||
29 | 30 | ||
30 | 31 | ||
31 | #define vmw_crtc_to_ldu(x) \ | 32 | #define vmw_crtc_to_ldu(x) \ |
diff --git a/drivers/gpu/drm/vmwgfx/vmwgfx_scrn.c b/drivers/gpu/drm/vmwgfx/vmwgfx_scrn.c index b295463a60b3..7dc591d04d9a 100644 --- a/drivers/gpu/drm/vmwgfx/vmwgfx_scrn.c +++ b/drivers/gpu/drm/vmwgfx/vmwgfx_scrn.c | |||
@@ -26,6 +26,7 @@ | |||
26 | **************************************************************************/ | 26 | **************************************************************************/ |
27 | 27 | ||
28 | #include "vmwgfx_kms.h" | 28 | #include "vmwgfx_kms.h" |
29 | #include <drm/drm_plane_helper.h> | ||
29 | 30 | ||
30 | 31 | ||
31 | #define vmw_crtc_to_sou(x) \ | 32 | #define vmw_crtc_to_sou(x) \ |
diff --git a/drivers/staging/imx-drm/imx-drm-core.c b/drivers/staging/imx-drm/imx-drm-core.c index 9cb222e2996f..2f8007241734 100644 --- a/drivers/staging/imx-drm/imx-drm-core.c +++ b/drivers/staging/imx-drm/imx-drm-core.c | |||
@@ -24,6 +24,7 @@ | |||
24 | #include <drm/drm_crtc_helper.h> | 24 | #include <drm/drm_crtc_helper.h> |
25 | #include <drm/drm_gem_cma_helper.h> | 25 | #include <drm/drm_gem_cma_helper.h> |
26 | #include <drm/drm_fb_cma_helper.h> | 26 | #include <drm/drm_fb_cma_helper.h> |
27 | #include <drm/drm_plane_helper.h> | ||
27 | 28 | ||
28 | #include "imx-drm.h" | 29 | #include "imx-drm.h" |
29 | 30 | ||
diff --git a/include/drm/drmP.h b/include/drm/drmP.h index 53ed87698a74..d7ebd7b207e3 100644 --- a/include/drm/drmP.h +++ b/include/drm/drmP.h | |||
@@ -125,8 +125,8 @@ struct dma_buf_attachment; | |||
125 | extern __printf(2, 3) | 125 | extern __printf(2, 3) |
126 | void drm_ut_debug_printk(const char *function_name, | 126 | void drm_ut_debug_printk(const char *function_name, |
127 | const char *format, ...); | 127 | const char *format, ...); |
128 | extern __printf(2, 3) | 128 | extern __printf(1, 2) |
129 | void drm_err(const char *func, const char *format, ...); | 129 | void drm_err(const char *format, ...); |
130 | 130 | ||
131 | /***********************************************************************/ | 131 | /***********************************************************************/ |
132 | /** \name DRM template customization defaults */ | 132 | /** \name DRM template customization defaults */ |
@@ -155,7 +155,7 @@ void drm_err(const char *func, const char *format, ...); | |||
155 | * \param arg arguments | 155 | * \param arg arguments |
156 | */ | 156 | */ |
157 | #define DRM_ERROR(fmt, ...) \ | 157 | #define DRM_ERROR(fmt, ...) \ |
158 | drm_err(__func__, fmt, ##__VA_ARGS__) | 158 | drm_err(fmt, ##__VA_ARGS__) |
159 | 159 | ||
160 | /** | 160 | /** |
161 | * Rate limited error output. Like DRM_ERROR() but won't flood the log. | 161 | * Rate limited error output. Like DRM_ERROR() but won't flood the log. |
@@ -170,7 +170,7 @@ void drm_err(const char *func, const char *format, ...); | |||
170 | DEFAULT_RATELIMIT_BURST); \ | 170 | DEFAULT_RATELIMIT_BURST); \ |
171 | \ | 171 | \ |
172 | if (__ratelimit(&_rs)) \ | 172 | if (__ratelimit(&_rs)) \ |
173 | drm_err(__func__, fmt, ##__VA_ARGS__); \ | 173 | drm_err(fmt, ##__VA_ARGS__); \ |
174 | }) | 174 | }) |
175 | 175 | ||
176 | #define DRM_INFO(fmt, ...) \ | 176 | #define DRM_INFO(fmt, ...) \ |
diff --git a/include/drm/drm_atomic.h b/include/drm/drm_atomic.h new file mode 100644 index 000000000000..9d919168bc11 --- /dev/null +++ b/include/drm/drm_atomic.h | |||
@@ -0,0 +1,67 @@ | |||
1 | /* | ||
2 | * Copyright (C) 2014 Red Hat | ||
3 | * Copyright (C) 2014 Intel Corp. | ||
4 | * | ||
5 | * Permission is hereby granted, free of charge, to any person obtaining a | ||
6 | * copy of this software and associated documentation files (the "Software"), | ||
7 | * to deal in the Software without restriction, including without limitation | ||
8 | * the rights to use, copy, modify, merge, publish, distribute, sublicense, | ||
9 | * and/or sell copies of the Software, and to permit persons to whom the | ||
10 | * Software is furnished to do so, subject to the following conditions: | ||
11 | * | ||
12 | * The above copyright notice and this permission notice shall be included in | ||
13 | * all copies or substantial portions of the Software. | ||
14 | * | ||
15 | * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR | ||
16 | * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, | ||
17 | * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL | ||
18 | * THE COPYRIGHT HOLDER(S) OR AUTHOR(S) BE LIABLE FOR ANY CLAIM, DAMAGES OR | ||
19 | * OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, | ||
20 | * ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR | ||
21 | * OTHER DEALINGS IN THE SOFTWARE. | ||
22 | * | ||
23 | * Authors: | ||
24 | * Rob Clark <robdclark@gmail.com> | ||
25 | * Daniel Vetter <daniel.vetter@ffwll.ch> | ||
26 | */ | ||
27 | |||
28 | #ifndef DRM_ATOMIC_H_ | ||
29 | #define DRM_ATOMIC_H_ | ||
30 | |||
31 | struct drm_atomic_state * __must_check | ||
32 | drm_atomic_state_alloc(struct drm_device *dev); | ||
33 | void drm_atomic_state_clear(struct drm_atomic_state *state); | ||
34 | void drm_atomic_state_free(struct drm_atomic_state *state); | ||
35 | |||
36 | struct drm_crtc_state * __must_check | ||
37 | drm_atomic_get_crtc_state(struct drm_atomic_state *state, | ||
38 | struct drm_crtc *crtc); | ||
39 | struct drm_plane_state * __must_check | ||
40 | drm_atomic_get_plane_state(struct drm_atomic_state *state, | ||
41 | struct drm_plane *plane); | ||
42 | struct drm_connector_state * __must_check | ||
43 | drm_atomic_get_connector_state(struct drm_atomic_state *state, | ||
44 | struct drm_connector *connector); | ||
45 | |||
46 | int __must_check | ||
47 | drm_atomic_set_crtc_for_plane(struct drm_plane_state *plane_state, | ||
48 | struct drm_crtc *crtc); | ||
49 | void drm_atomic_set_fb_for_plane(struct drm_plane_state *plane_state, | ||
50 | struct drm_framebuffer *fb); | ||
51 | int __must_check | ||
52 | drm_atomic_set_crtc_for_connector(struct drm_connector_state *conn_state, | ||
53 | struct drm_crtc *crtc); | ||
54 | int __must_check | ||
55 | drm_atomic_add_affected_connectors(struct drm_atomic_state *state, | ||
56 | struct drm_crtc *crtc); | ||
57 | int | ||
58 | drm_atomic_connectors_for_crtc(struct drm_atomic_state *state, | ||
59 | struct drm_crtc *crtc); | ||
60 | |||
61 | void drm_atomic_legacy_backoff(struct drm_atomic_state *state); | ||
62 | |||
63 | int __must_check drm_atomic_check_only(struct drm_atomic_state *state); | ||
64 | int __must_check drm_atomic_commit(struct drm_atomic_state *state); | ||
65 | int __must_check drm_atomic_async_commit(struct drm_atomic_state *state); | ||
66 | |||
67 | #endif /* DRM_ATOMIC_H_ */ | ||
diff --git a/include/drm/drm_atomic_helper.h b/include/drm/drm_atomic_helper.h new file mode 100644 index 000000000000..67e3c4645ae0 --- /dev/null +++ b/include/drm/drm_atomic_helper.h | |||
@@ -0,0 +1,97 @@ | |||
1 | /* | ||
2 | * Copyright (C) 2014 Red Hat | ||
3 | * Copyright (C) 2014 Intel Corp. | ||
4 | * | ||
5 | * Permission is hereby granted, free of charge, to any person obtaining a | ||
6 | * copy of this software and associated documentation files (the "Software"), | ||
7 | * to deal in the Software without restriction, including without limitation | ||
8 | * the rights to use, copy, modify, merge, publish, distribute, sublicense, | ||
9 | * and/or sell copies of the Software, and to permit persons to whom the | ||
10 | * Software is furnished to do so, subject to the following conditions: | ||
11 | * | ||
12 | * The above copyright notice and this permission notice shall be included in | ||
13 | * all copies or substantial portions of the Software. | ||
14 | * | ||
15 | * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR | ||
16 | * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, | ||
17 | * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL | ||
18 | * THE COPYRIGHT HOLDER(S) OR AUTHOR(S) BE LIABLE FOR ANY CLAIM, DAMAGES OR | ||
19 | * OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, | ||
20 | * ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR | ||
21 | * OTHER DEALINGS IN THE SOFTWARE. | ||
22 | * | ||
23 | * Authors: | ||
24 | * Rob Clark <robdclark@gmail.com> | ||
25 | * Daniel Vetter <daniel.vetter@ffwll.ch> | ||
26 | */ | ||
27 | |||
28 | #ifndef DRM_ATOMIC_HELPER_H_ | ||
29 | #define DRM_ATOMIC_HELPER_H_ | ||
30 | |||
31 | int drm_atomic_helper_check(struct drm_device *dev, | ||
32 | struct drm_atomic_state *state); | ||
33 | int drm_atomic_helper_commit(struct drm_device *dev, | ||
34 | struct drm_atomic_state *state, | ||
35 | bool async); | ||
36 | |||
37 | void drm_atomic_helper_commit_pre_planes(struct drm_device *dev, | ||
38 | struct drm_atomic_state *state); | ||
39 | void drm_atomic_helper_commit_post_planes(struct drm_device *dev, | ||
40 | struct drm_atomic_state *old_state); | ||
41 | |||
42 | int drm_atomic_helper_prepare_planes(struct drm_device *dev, | ||
43 | struct drm_atomic_state *state); | ||
44 | void drm_atomic_helper_commit_planes(struct drm_device *dev, | ||
45 | struct drm_atomic_state *state); | ||
46 | void drm_atomic_helper_cleanup_planes(struct drm_device *dev, | ||
47 | struct drm_atomic_state *old_state); | ||
48 | |||
49 | void drm_atomic_helper_swap_state(struct drm_device *dev, | ||
50 | struct drm_atomic_state *state); | ||
51 | |||
52 | /* implementations for legacy interfaces */ | ||
53 | int drm_atomic_helper_update_plane(struct drm_plane *plane, | ||
54 | struct drm_crtc *crtc, | ||
55 | struct drm_framebuffer *fb, | ||
56 | int crtc_x, int crtc_y, | ||
57 | unsigned int crtc_w, unsigned int crtc_h, | ||
58 | uint32_t src_x, uint32_t src_y, | ||
59 | uint32_t src_w, uint32_t src_h); | ||
60 | int drm_atomic_helper_disable_plane(struct drm_plane *plane); | ||
61 | int drm_atomic_helper_set_config(struct drm_mode_set *set); | ||
62 | |||
63 | int drm_atomic_helper_crtc_set_property(struct drm_crtc *crtc, | ||
64 | struct drm_property *property, | ||
65 | uint64_t val); | ||
66 | int drm_atomic_helper_plane_set_property(struct drm_plane *plane, | ||
67 | struct drm_property *property, | ||
68 | uint64_t val); | ||
69 | int drm_atomic_helper_connector_set_property(struct drm_connector *connector, | ||
70 | struct drm_property *property, | ||
71 | uint64_t val); | ||
72 | int drm_atomic_helper_page_flip(struct drm_crtc *crtc, | ||
73 | struct drm_framebuffer *fb, | ||
74 | struct drm_pending_vblank_event *event, | ||
75 | uint32_t flags); | ||
76 | |||
77 | /* default implementations for state handling */ | ||
78 | void drm_atomic_helper_crtc_reset(struct drm_crtc *crtc); | ||
79 | struct drm_crtc_state * | ||
80 | drm_atomic_helper_crtc_duplicate_state(struct drm_crtc *crtc); | ||
81 | void drm_atomic_helper_crtc_destroy_state(struct drm_crtc *crtc, | ||
82 | struct drm_crtc_state *state); | ||
83 | |||
84 | void drm_atomic_helper_plane_reset(struct drm_plane *plane); | ||
85 | struct drm_plane_state * | ||
86 | drm_atomic_helper_plane_duplicate_state(struct drm_plane *plane); | ||
87 | void drm_atomic_helper_plane_destroy_state(struct drm_plane *plane, | ||
88 | struct drm_plane_state *state); | ||
89 | |||
90 | void drm_atomic_helper_connector_reset(struct drm_connector *connector); | ||
91 | struct drm_connector_state * | ||
92 | drm_atomic_helper_connector_duplicate_state(struct drm_connector *connector); | ||
93 | void drm_atomic_helper_connector_destroy_state(struct drm_connector *connector, | ||
94 | struct drm_connector_state *state); | ||
95 | |||
96 | |||
97 | #endif /* DRM_ATOMIC_HELPER_H_ */ | ||
diff --git a/include/drm/drm_crtc.h b/include/drm/drm_crtc.h index c40070a92d6b..bc1cc3ce05c4 100644 --- a/include/drm/drm_crtc.h +++ b/include/drm/drm_crtc.h | |||
@@ -42,6 +42,7 @@ struct drm_object_properties; | |||
42 | struct drm_file; | 42 | struct drm_file; |
43 | struct drm_clip_rect; | 43 | struct drm_clip_rect; |
44 | struct device_node; | 44 | struct device_node; |
45 | struct fence; | ||
45 | 46 | ||
46 | #define DRM_MODE_OBJECT_CRTC 0xcccccccc | 47 | #define DRM_MODE_OBJECT_CRTC 0xcccccccc |
47 | #define DRM_MODE_OBJECT_CONNECTOR 0xc0c0c0c0 | 48 | #define DRM_MODE_OBJECT_CONNECTOR 0xc0c0c0c0 |
@@ -142,8 +143,8 @@ struct drm_framebuffer_funcs { | |||
142 | int (*create_handle)(struct drm_framebuffer *fb, | 143 | int (*create_handle)(struct drm_framebuffer *fb, |
143 | struct drm_file *file_priv, | 144 | struct drm_file *file_priv, |
144 | unsigned int *handle); | 145 | unsigned int *handle); |
145 | /** | 146 | /* |
146 | * Optinal callback for the dirty fb ioctl. | 147 | * Optional callback for the dirty fb ioctl. |
147 | * | 148 | * |
148 | * Userspace can notify the driver via this callback | 149 | * Userspace can notify the driver via this callback |
149 | * that a area of the framebuffer has changed and should | 150 | * that a area of the framebuffer has changed and should |
@@ -224,19 +225,57 @@ struct drm_encoder; | |||
224 | struct drm_pending_vblank_event; | 225 | struct drm_pending_vblank_event; |
225 | struct drm_plane; | 226 | struct drm_plane; |
226 | struct drm_bridge; | 227 | struct drm_bridge; |
228 | struct drm_atomic_state; | ||
229 | |||
230 | /** | ||
231 | * struct drm_crtc_state - mutable CRTC state | ||
232 | * @enable: whether the CRTC should be enabled, gates all other state | ||
233 | * @mode_changed: for use by helpers and drivers when computing state updates | ||
234 | * @last_vblank_count: for helpers and drivers to capture the vblank of the | ||
235 | * update to ensure framebuffer cleanup isn't done too early | ||
236 | * @planes_changed: for use by helpers and drivers when computing state updates | ||
237 | * @adjusted_mode: for use by helpers and drivers to compute adjusted mode timings | ||
238 | * @mode: current mode timings | ||
239 | * @event: optional pointer to a DRM event to signal upon completion of the | ||
240 | * state update | ||
241 | * @state: backpointer to global drm_atomic_state | ||
242 | */ | ||
243 | struct drm_crtc_state { | ||
244 | bool enable; | ||
245 | |||
246 | /* computed state bits used by helpers and drivers */ | ||
247 | bool planes_changed : 1; | ||
248 | bool mode_changed : 1; | ||
249 | |||
250 | /* last_vblank_count: for vblank waits before cleanup */ | ||
251 | u32 last_vblank_count; | ||
252 | |||
253 | /* adjusted_mode: for use by helpers and drivers */ | ||
254 | struct drm_display_mode adjusted_mode; | ||
255 | |||
256 | struct drm_display_mode mode; | ||
257 | |||
258 | struct drm_pending_vblank_event *event; | ||
259 | |||
260 | struct drm_atomic_state *state; | ||
261 | }; | ||
227 | 262 | ||
228 | /** | 263 | /** |
229 | * drm_crtc_funcs - control CRTCs for a given device | 264 | * struct drm_crtc_funcs - control CRTCs for a given device |
230 | * @save: save CRTC state | 265 | * @save: save CRTC state |
231 | * @restore: restore CRTC state | 266 | * @restore: restore CRTC state |
232 | * @reset: reset CRTC after state has been invalidated (e.g. resume) | 267 | * @reset: reset CRTC after state has been invalidated (e.g. resume) |
233 | * @cursor_set: setup the cursor | 268 | * @cursor_set: setup the cursor |
269 | * @cursor_set2: setup the cursor with hotspot, superseeds @cursor_set if set | ||
234 | * @cursor_move: move the cursor | 270 | * @cursor_move: move the cursor |
235 | * @gamma_set: specify color ramp for CRTC | 271 | * @gamma_set: specify color ramp for CRTC |
236 | * @destroy: deinit and free object | 272 | * @destroy: deinit and free object |
237 | * @set_property: called when a property is changed | 273 | * @set_property: called when a property is changed |
238 | * @set_config: apply a new CRTC configuration | 274 | * @set_config: apply a new CRTC configuration |
239 | * @page_flip: initiate a page flip | 275 | * @page_flip: initiate a page flip |
276 | * @atomic_duplicate_state: duplicate the atomic state for this CRTC | ||
277 | * @atomic_destroy_state: destroy an atomic state for this CRTC | ||
278 | * @atomic_set_property: set a property on an atomic state for this CRTC | ||
240 | * | 279 | * |
241 | * The drm_crtc_funcs structure is the central CRTC management structure | 280 | * The drm_crtc_funcs structure is the central CRTC management structure |
242 | * in the DRM. Each CRTC controls one or more connectors (note that the name | 281 | * in the DRM. Each CRTC controls one or more connectors (note that the name |
@@ -287,16 +326,28 @@ struct drm_crtc_funcs { | |||
287 | 326 | ||
288 | int (*set_property)(struct drm_crtc *crtc, | 327 | int (*set_property)(struct drm_crtc *crtc, |
289 | struct drm_property *property, uint64_t val); | 328 | struct drm_property *property, uint64_t val); |
329 | |||
330 | /* atomic update handling */ | ||
331 | struct drm_crtc_state *(*atomic_duplicate_state)(struct drm_crtc *crtc); | ||
332 | void (*atomic_destroy_state)(struct drm_crtc *crtc, | ||
333 | struct drm_crtc_state *state); | ||
334 | int (*atomic_set_property)(struct drm_crtc *crtc, | ||
335 | struct drm_crtc_state *state, | ||
336 | struct drm_property *property, | ||
337 | uint64_t val); | ||
290 | }; | 338 | }; |
291 | 339 | ||
292 | /** | 340 | /** |
293 | * drm_crtc - central CRTC control structure | 341 | * struct drm_crtc - central CRTC control structure |
294 | * @dev: parent DRM device | 342 | * @dev: parent DRM device |
343 | * @port: OF node used by drm_of_find_possible_crtcs() | ||
295 | * @head: list management | 344 | * @head: list management |
296 | * @mutex: per-CRTC locking | 345 | * @mutex: per-CRTC locking |
297 | * @base: base KMS object for ID tracking etc. | 346 | * @base: base KMS object for ID tracking etc. |
298 | * @primary: primary plane for this CRTC | 347 | * @primary: primary plane for this CRTC |
299 | * @cursor: cursor plane for this CRTC | 348 | * @cursor: cursor plane for this CRTC |
349 | * @cursor_x: current x position of the cursor, used for universal cursor planes | ||
350 | * @cursor_y: current y position of the cursor, used for universal cursor planes | ||
300 | * @enabled: is this CRTC enabled? | 351 | * @enabled: is this CRTC enabled? |
301 | * @mode: current mode timings | 352 | * @mode: current mode timings |
302 | * @hwmode: mode timings as programmed to hw regs | 353 | * @hwmode: mode timings as programmed to hw regs |
@@ -309,10 +360,13 @@ struct drm_crtc_funcs { | |||
309 | * @gamma_size: size of gamma ramp | 360 | * @gamma_size: size of gamma ramp |
310 | * @gamma_store: gamma ramp values | 361 | * @gamma_store: gamma ramp values |
311 | * @framedur_ns: precise frame timing | 362 | * @framedur_ns: precise frame timing |
312 | * @framedur_ns: precise line timing | 363 | * @linedur_ns: precise line timing |
313 | * @pixeldur_ns: precise pixel timing | 364 | * @pixeldur_ns: precise pixel timing |
314 | * @helper_private: mid-layer private data | 365 | * @helper_private: mid-layer private data |
315 | * @properties: property tracking for this CRTC | 366 | * @properties: property tracking for this CRTC |
367 | * @state: current atomic state for this CRTC | ||
368 | * @acquire_ctx: per-CRTC implicit acquire context used by atomic drivers for | ||
369 | * legacy ioctls | ||
316 | * | 370 | * |
317 | * Each CRTC may have one or more connectors associated with it. This structure | 371 | * Each CRTC may have one or more connectors associated with it. This structure |
318 | * allows the CRTC to be controlled. | 372 | * allows the CRTC to be controlled. |
@@ -322,7 +376,7 @@ struct drm_crtc { | |||
322 | struct device_node *port; | 376 | struct device_node *port; |
323 | struct list_head head; | 377 | struct list_head head; |
324 | 378 | ||
325 | /** | 379 | /* |
326 | * crtc mutex | 380 | * crtc mutex |
327 | * | 381 | * |
328 | * This provides a read lock for the overall crtc state (mode, dpms | 382 | * This provides a read lock for the overall crtc state (mode, dpms |
@@ -368,6 +422,8 @@ struct drm_crtc { | |||
368 | 422 | ||
369 | struct drm_object_properties properties; | 423 | struct drm_object_properties properties; |
370 | 424 | ||
425 | struct drm_crtc_state *state; | ||
426 | |||
371 | /* | 427 | /* |
372 | * For legacy crtc ioctls so that atomic drivers can get at the locking | 428 | * For legacy crtc ioctls so that atomic drivers can get at the locking |
373 | * acquire context. | 429 | * acquire context. |
@@ -375,9 +431,22 @@ struct drm_crtc { | |||
375 | struct drm_modeset_acquire_ctx *acquire_ctx; | 431 | struct drm_modeset_acquire_ctx *acquire_ctx; |
376 | }; | 432 | }; |
377 | 433 | ||
434 | /** | ||
435 | * struct drm_connector_state - mutable connector state | ||
436 | * @crtc: CRTC to connect connector to, NULL if disabled | ||
437 | * @best_encoder: can be used by helpers and drivers to select the encoder | ||
438 | * @state: backpointer to global drm_atomic_state | ||
439 | */ | ||
440 | struct drm_connector_state { | ||
441 | struct drm_crtc *crtc; | ||
442 | |||
443 | struct drm_encoder *best_encoder; | ||
444 | |||
445 | struct drm_atomic_state *state; | ||
446 | }; | ||
378 | 447 | ||
379 | /** | 448 | /** |
380 | * drm_connector_funcs - control connectors on a given device | 449 | * struct drm_connector_funcs - control connectors on a given device |
381 | * @dpms: set power state (see drm_crtc_funcs above) | 450 | * @dpms: set power state (see drm_crtc_funcs above) |
382 | * @save: save connector state | 451 | * @save: save connector state |
383 | * @restore: restore connector state | 452 | * @restore: restore connector state |
@@ -387,6 +456,9 @@ struct drm_crtc { | |||
387 | * @set_property: property for this connector may need an update | 456 | * @set_property: property for this connector may need an update |
388 | * @destroy: make object go away | 457 | * @destroy: make object go away |
389 | * @force: notify the driver that the connector is forced on | 458 | * @force: notify the driver that the connector is forced on |
459 | * @atomic_duplicate_state: duplicate the atomic state for this connector | ||
460 | * @atomic_destroy_state: destroy an atomic state for this connector | ||
461 | * @atomic_set_property: set a property on an atomic state for this connector | ||
390 | * | 462 | * |
391 | * Each CRTC may have one or more connectors attached to it. The functions | 463 | * Each CRTC may have one or more connectors attached to it. The functions |
392 | * below allow the core DRM code to control connectors, enumerate available modes, | 464 | * below allow the core DRM code to control connectors, enumerate available modes, |
@@ -411,10 +483,19 @@ struct drm_connector_funcs { | |||
411 | uint64_t val); | 483 | uint64_t val); |
412 | void (*destroy)(struct drm_connector *connector); | 484 | void (*destroy)(struct drm_connector *connector); |
413 | void (*force)(struct drm_connector *connector); | 485 | void (*force)(struct drm_connector *connector); |
486 | |||
487 | /* atomic update handling */ | ||
488 | struct drm_connector_state *(*atomic_duplicate_state)(struct drm_connector *connector); | ||
489 | void (*atomic_destroy_state)(struct drm_connector *connector, | ||
490 | struct drm_connector_state *state); | ||
491 | int (*atomic_set_property)(struct drm_connector *connector, | ||
492 | struct drm_connector_state *state, | ||
493 | struct drm_property *property, | ||
494 | uint64_t val); | ||
414 | }; | 495 | }; |
415 | 496 | ||
416 | /** | 497 | /** |
417 | * drm_encoder_funcs - encoder controls | 498 | * struct drm_encoder_funcs - encoder controls |
418 | * @reset: reset state (e.g. at init or resume time) | 499 | * @reset: reset state (e.g. at init or resume time) |
419 | * @destroy: cleanup and free associated data | 500 | * @destroy: cleanup and free associated data |
420 | * | 501 | * |
@@ -428,7 +509,7 @@ struct drm_encoder_funcs { | |||
428 | #define DRM_CONNECTOR_MAX_ENCODER 3 | 509 | #define DRM_CONNECTOR_MAX_ENCODER 3 |
429 | 510 | ||
430 | /** | 511 | /** |
431 | * drm_encoder - central DRM encoder structure | 512 | * struct drm_encoder - central DRM encoder structure |
432 | * @dev: parent DRM device | 513 | * @dev: parent DRM device |
433 | * @head: list management | 514 | * @head: list management |
434 | * @base: base KMS object | 515 | * @base: base KMS object |
@@ -472,7 +553,7 @@ struct drm_encoder { | |||
472 | #define MAX_ELD_BYTES 128 | 553 | #define MAX_ELD_BYTES 128 |
473 | 554 | ||
474 | /** | 555 | /** |
475 | * drm_connector - central DRM connector control structure | 556 | * struct drm_connector - central DRM connector control structure |
476 | * @dev: parent DRM device | 557 | * @dev: parent DRM device |
477 | * @kdev: kernel device for sysfs attributes | 558 | * @kdev: kernel device for sysfs attributes |
478 | * @attr: sysfs attributes | 559 | * @attr: sysfs attributes |
@@ -483,6 +564,7 @@ struct drm_encoder { | |||
483 | * @connector_type_id: index into connector type enum | 564 | * @connector_type_id: index into connector type enum |
484 | * @interlace_allowed: can this connector handle interlaced modes? | 565 | * @interlace_allowed: can this connector handle interlaced modes? |
485 | * @doublescan_allowed: can this connector handle doublescan? | 566 | * @doublescan_allowed: can this connector handle doublescan? |
567 | * @stereo_allowed: can this connector handle stereo modes? | ||
486 | * @modes: modes available on this connector (from fill_modes() + user) | 568 | * @modes: modes available on this connector (from fill_modes() + user) |
487 | * @status: one of the drm_connector_status enums (connected, not, or unknown) | 569 | * @status: one of the drm_connector_status enums (connected, not, or unknown) |
488 | * @probed_modes: list of modes derived directly from the display | 570 | * @probed_modes: list of modes derived directly from the display |
@@ -490,10 +572,13 @@ struct drm_encoder { | |||
490 | * @funcs: connector control functions | 572 | * @funcs: connector control functions |
491 | * @edid_blob_ptr: DRM property containing EDID if present | 573 | * @edid_blob_ptr: DRM property containing EDID if present |
492 | * @properties: property tracking for this connector | 574 | * @properties: property tracking for this connector |
575 | * @path_blob_ptr: DRM blob property data for the DP MST path property | ||
493 | * @polled: a %DRM_CONNECTOR_POLL_<foo> value for core driven polling | 576 | * @polled: a %DRM_CONNECTOR_POLL_<foo> value for core driven polling |
494 | * @dpms: current dpms state | 577 | * @dpms: current dpms state |
495 | * @helper_private: mid-layer private data | 578 | * @helper_private: mid-layer private data |
579 | * @cmdline_mode: mode line parsed from the kernel cmdline for this connector | ||
496 | * @force: a %DRM_FORCE_<foo> state for forced mode sets | 580 | * @force: a %DRM_FORCE_<foo> state for forced mode sets |
581 | * @override_edid: has the EDID been overwritten through debugfs for testing? | ||
497 | * @encoder_ids: valid encoders for this connector | 582 | * @encoder_ids: valid encoders for this connector |
498 | * @encoder: encoder driving this connector, if any | 583 | * @encoder: encoder driving this connector, if any |
499 | * @eld: EDID-like data, if present | 584 | * @eld: EDID-like data, if present |
@@ -503,6 +588,9 @@ struct drm_encoder { | |||
503 | * @video_latency: video latency info from ELD, if found | 588 | * @video_latency: video latency info from ELD, if found |
504 | * @audio_latency: audio latency info from ELD, if found | 589 | * @audio_latency: audio latency info from ELD, if found |
505 | * @null_edid_counter: track sinks that give us all zeros for the EDID | 590 | * @null_edid_counter: track sinks that give us all zeros for the EDID |
591 | * @bad_edid_counter: track sinks that give us an EDID with invalid checksum | ||
592 | * @debugfs_entry: debugfs directory for this connector | ||
593 | * @state: current atomic state for this connector | ||
506 | * | 594 | * |
507 | * Each connector may be connected to one or more CRTCs, or may be clonable by | 595 | * Each connector may be connected to one or more CRTCs, or may be clonable by |
508 | * another connector if they can share a CRTC. Each connector also has a specific | 596 | * another connector if they can share a CRTC. Each connector also has a specific |
@@ -563,14 +651,54 @@ struct drm_connector { | |||
563 | unsigned bad_edid_counter; | 651 | unsigned bad_edid_counter; |
564 | 652 | ||
565 | struct dentry *debugfs_entry; | 653 | struct dentry *debugfs_entry; |
654 | |||
655 | struct drm_connector_state *state; | ||
656 | }; | ||
657 | |||
658 | /** | ||
659 | * struct drm_plane_state - mutable plane state | ||
660 | * @crtc: currently bound CRTC, NULL if disabled | ||
661 | * @fb: currently bound framebuffer | ||
662 | * @fence: optional fence to wait for before scanning out @fb | ||
663 | * @crtc_x: left position of visible portion of plane on crtc | ||
664 | * @crtc_y: upper position of visible portion of plane on crtc | ||
665 | * @crtc_w: width of visible portion of plane on crtc | ||
666 | * @crtc_h: height of visible portion of plane on crtc | ||
667 | * @src_x: left position of visible portion of plane within | ||
668 | * plane (in 16.16) | ||
669 | * @src_y: upper position of visible portion of plane within | ||
670 | * plane (in 16.16) | ||
671 | * @src_w: width of visible portion of plane (in 16.16) | ||
672 | * @src_h: height of visible portion of plane (in 16.16) | ||
673 | * @state: backpointer to global drm_atomic_state | ||
674 | */ | ||
675 | struct drm_plane_state { | ||
676 | struct drm_crtc *crtc; | ||
677 | struct drm_framebuffer *fb; | ||
678 | struct fence *fence; | ||
679 | |||
680 | /* Signed dest location allows it to be partially off screen */ | ||
681 | int32_t crtc_x, crtc_y; | ||
682 | uint32_t crtc_w, crtc_h; | ||
683 | |||
684 | /* Source values are 16.16 fixed point */ | ||
685 | uint32_t src_x, src_y; | ||
686 | uint32_t src_h, src_w; | ||
687 | |||
688 | struct drm_atomic_state *state; | ||
566 | }; | 689 | }; |
567 | 690 | ||
691 | |||
568 | /** | 692 | /** |
569 | * drm_plane_funcs - driver plane control functions | 693 | * struct drm_plane_funcs - driver plane control functions |
570 | * @update_plane: update the plane configuration | 694 | * @update_plane: update the plane configuration |
571 | * @disable_plane: shut down the plane | 695 | * @disable_plane: shut down the plane |
572 | * @destroy: clean up plane resources | 696 | * @destroy: clean up plane resources |
697 | * @reset: reset plane after state has been invalidated (e.g. resume) | ||
573 | * @set_property: called when a property is changed | 698 | * @set_property: called when a property is changed |
699 | * @atomic_duplicate_state: duplicate the atomic state for this plane | ||
700 | * @atomic_destroy_state: destroy an atomic state for this plane | ||
701 | * @atomic_set_property: set a property on an atomic state for this plane | ||
574 | */ | 702 | */ |
575 | struct drm_plane_funcs { | 703 | struct drm_plane_funcs { |
576 | int (*update_plane)(struct drm_plane *plane, | 704 | int (*update_plane)(struct drm_plane *plane, |
@@ -585,6 +713,15 @@ struct drm_plane_funcs { | |||
585 | 713 | ||
586 | int (*set_property)(struct drm_plane *plane, | 714 | int (*set_property)(struct drm_plane *plane, |
587 | struct drm_property *property, uint64_t val); | 715 | struct drm_property *property, uint64_t val); |
716 | |||
717 | /* atomic update handling */ | ||
718 | struct drm_plane_state *(*atomic_duplicate_state)(struct drm_plane *plane); | ||
719 | void (*atomic_destroy_state)(struct drm_plane *plane, | ||
720 | struct drm_plane_state *state); | ||
721 | int (*atomic_set_property)(struct drm_plane *plane, | ||
722 | struct drm_plane_state *state, | ||
723 | struct drm_property *property, | ||
724 | uint64_t val); | ||
588 | }; | 725 | }; |
589 | 726 | ||
590 | enum drm_plane_type { | 727 | enum drm_plane_type { |
@@ -594,7 +731,7 @@ enum drm_plane_type { | |||
594 | }; | 731 | }; |
595 | 732 | ||
596 | /** | 733 | /** |
597 | * drm_plane - central DRM plane control structure | 734 | * struct drm_plane - central DRM plane control structure |
598 | * @dev: DRM device this plane belongs to | 735 | * @dev: DRM device this plane belongs to |
599 | * @head: for list management | 736 | * @head: for list management |
600 | * @base: base mode object | 737 | * @base: base mode object |
@@ -603,9 +740,12 @@ enum drm_plane_type { | |||
603 | * @format_count: number of formats supported | 740 | * @format_count: number of formats supported |
604 | * @crtc: currently bound CRTC | 741 | * @crtc: currently bound CRTC |
605 | * @fb: currently bound fb | 742 | * @fb: currently bound fb |
743 | * @old_fb: Temporary tracking of the old fb while a modeset is ongoing. Used by | ||
744 | * drm_mode_set_config_internal() to implement correct refcounting. | ||
606 | * @funcs: helper functions | 745 | * @funcs: helper functions |
607 | * @properties: property tracking for this plane | 746 | * @properties: property tracking for this plane |
608 | * @type: type of plane (overlay, primary, cursor) | 747 | * @type: type of plane (overlay, primary, cursor) |
748 | * @state: current atomic state for this plane | ||
609 | */ | 749 | */ |
610 | struct drm_plane { | 750 | struct drm_plane { |
611 | struct drm_device *dev; | 751 | struct drm_device *dev; |
@@ -620,8 +760,6 @@ struct drm_plane { | |||
620 | struct drm_crtc *crtc; | 760 | struct drm_crtc *crtc; |
621 | struct drm_framebuffer *fb; | 761 | struct drm_framebuffer *fb; |
622 | 762 | ||
623 | /* Temporary tracking of the old fb while a modeset is ongoing. Used | ||
624 | * by drm_mode_set_config_internal to implement correct refcounting. */ | ||
625 | struct drm_framebuffer *old_fb; | 763 | struct drm_framebuffer *old_fb; |
626 | 764 | ||
627 | const struct drm_plane_funcs *funcs; | 765 | const struct drm_plane_funcs *funcs; |
@@ -629,10 +767,14 @@ struct drm_plane { | |||
629 | struct drm_object_properties properties; | 767 | struct drm_object_properties properties; |
630 | 768 | ||
631 | enum drm_plane_type type; | 769 | enum drm_plane_type type; |
770 | |||
771 | void *helper_private; | ||
772 | |||
773 | struct drm_plane_state *state; | ||
632 | }; | 774 | }; |
633 | 775 | ||
634 | /** | 776 | /** |
635 | * drm_bridge_funcs - drm_bridge control functions | 777 | * struct drm_bridge_funcs - drm_bridge control functions |
636 | * @mode_fixup: Try to fixup (or reject entirely) proposed mode for this bridge | 778 | * @mode_fixup: Try to fixup (or reject entirely) proposed mode for this bridge |
637 | * @disable: Called right before encoder prepare, disables the bridge | 779 | * @disable: Called right before encoder prepare, disables the bridge |
638 | * @post_disable: Called right after encoder prepare, for lockstepped disable | 780 | * @post_disable: Called right after encoder prepare, for lockstepped disable |
@@ -656,7 +798,7 @@ struct drm_bridge_funcs { | |||
656 | }; | 798 | }; |
657 | 799 | ||
658 | /** | 800 | /** |
659 | * drm_bridge - central DRM bridge control structure | 801 | * struct drm_bridge - central DRM bridge control structure |
660 | * @dev: DRM device this bridge belongs to | 802 | * @dev: DRM device this bridge belongs to |
661 | * @head: list management | 803 | * @head: list management |
662 | * @base: base mode object | 804 | * @base: base mode object |
@@ -674,8 +816,33 @@ struct drm_bridge { | |||
674 | }; | 816 | }; |
675 | 817 | ||
676 | /** | 818 | /** |
677 | * drm_mode_set - new values for a CRTC config change | 819 | * struct struct drm_atomic_state - the global state object for atomic updates |
678 | * @head: list management | 820 | * @dev: parent DRM device |
821 | * @flags: state flags like async update | ||
822 | * @planes: pointer to array of plane pointers | ||
823 | * @plane_states: pointer to array of plane states pointers | ||
824 | * @crtcs: pointer to array of CRTC pointers | ||
825 | * @crtc_states: pointer to array of CRTC states pointers | ||
826 | * @connectors: pointer to array of connector pointers | ||
827 | * @connector_states: pointer to array of connector states pointers | ||
828 | * @acquire_ctx: acquire context for this atomic modeset state update | ||
829 | */ | ||
830 | struct drm_atomic_state { | ||
831 | struct drm_device *dev; | ||
832 | uint32_t flags; | ||
833 | struct drm_plane **planes; | ||
834 | struct drm_plane_state **plane_states; | ||
835 | struct drm_crtc **crtcs; | ||
836 | struct drm_crtc_state **crtc_states; | ||
837 | struct drm_connector **connectors; | ||
838 | struct drm_connector_state **connector_states; | ||
839 | |||
840 | struct drm_modeset_acquire_ctx *acquire_ctx; | ||
841 | }; | ||
842 | |||
843 | |||
844 | /** | ||
845 | * struct drm_mode_set - new values for a CRTC config change | ||
679 | * @fb: framebuffer to use for new config | 846 | * @fb: framebuffer to use for new config |
680 | * @crtc: CRTC whose configuration we're about to change | 847 | * @crtc: CRTC whose configuration we're about to change |
681 | * @mode: mode timings to use | 848 | * @mode: mode timings to use |
@@ -705,6 +872,9 @@ struct drm_mode_set { | |||
705 | * struct drm_mode_config_funcs - basic driver provided mode setting functions | 872 | * struct drm_mode_config_funcs - basic driver provided mode setting functions |
706 | * @fb_create: create a new framebuffer object | 873 | * @fb_create: create a new framebuffer object |
707 | * @output_poll_changed: function to handle output configuration changes | 874 | * @output_poll_changed: function to handle output configuration changes |
875 | * @atomic_check: check whether a give atomic state update is possible | ||
876 | * @atomic_commit: commit an atomic state update previously verified with | ||
877 | * atomic_check() | ||
708 | * | 878 | * |
709 | * Some global (i.e. not per-CRTC, connector, etc) mode setting functions that | 879 | * Some global (i.e. not per-CRTC, connector, etc) mode setting functions that |
710 | * involve drivers. | 880 | * involve drivers. |
@@ -714,13 +884,20 @@ struct drm_mode_config_funcs { | |||
714 | struct drm_file *file_priv, | 884 | struct drm_file *file_priv, |
715 | struct drm_mode_fb_cmd2 *mode_cmd); | 885 | struct drm_mode_fb_cmd2 *mode_cmd); |
716 | void (*output_poll_changed)(struct drm_device *dev); | 886 | void (*output_poll_changed)(struct drm_device *dev); |
887 | |||
888 | int (*atomic_check)(struct drm_device *dev, | ||
889 | struct drm_atomic_state *a); | ||
890 | int (*atomic_commit)(struct drm_device *dev, | ||
891 | struct drm_atomic_state *a, | ||
892 | bool async); | ||
717 | }; | 893 | }; |
718 | 894 | ||
719 | /** | 895 | /** |
720 | * drm_mode_group - group of mode setting resources for potential sub-grouping | 896 | * struct drm_mode_group - group of mode setting resources for potential sub-grouping |
721 | * @num_crtcs: CRTC count | 897 | * @num_crtcs: CRTC count |
722 | * @num_encoders: encoder count | 898 | * @num_encoders: encoder count |
723 | * @num_connectors: connector count | 899 | * @num_connectors: connector count |
900 | * @num_bridges: bridge count | ||
724 | * @id_list: list of KMS object IDs in this group | 901 | * @id_list: list of KMS object IDs in this group |
725 | * | 902 | * |
726 | * Currently this simply tracks the global mode setting state. But in the | 903 | * Currently this simply tracks the global mode setting state. But in the |
@@ -740,10 +917,14 @@ struct drm_mode_group { | |||
740 | }; | 917 | }; |
741 | 918 | ||
742 | /** | 919 | /** |
743 | * drm_mode_config - Mode configuration control structure | 920 | * struct drm_mode_config - Mode configuration control structure |
744 | * @mutex: mutex protecting KMS related lists and structures | 921 | * @mutex: mutex protecting KMS related lists and structures |
922 | * @connection_mutex: ww mutex protecting connector state and routing | ||
923 | * @acquire_ctx: global implicit acquire context used by atomic drivers for | ||
924 | * legacy ioctls | ||
745 | * @idr_mutex: mutex for KMS ID allocation and management | 925 | * @idr_mutex: mutex for KMS ID allocation and management |
746 | * @crtc_idr: main KMS ID tracking object | 926 | * @crtc_idr: main KMS ID tracking object |
927 | * @fb_lock: mutex to protect fb state and lists | ||
747 | * @num_fb: number of fbs available | 928 | * @num_fb: number of fbs available |
748 | * @fb_list: list of framebuffers available | 929 | * @fb_list: list of framebuffers available |
749 | * @num_connector: number of connectors on this device | 930 | * @num_connector: number of connectors on this device |
@@ -752,17 +933,28 @@ struct drm_mode_group { | |||
752 | * @bridge_list: list of bridge objects | 933 | * @bridge_list: list of bridge objects |
753 | * @num_encoder: number of encoders on this device | 934 | * @num_encoder: number of encoders on this device |
754 | * @encoder_list: list of encoder objects | 935 | * @encoder_list: list of encoder objects |
936 | * @num_overlay_plane: number of overlay planes on this device | ||
937 | * @num_total_plane: number of universal (i.e. with primary/curso) planes on this device | ||
938 | * @plane_list: list of plane objects | ||
755 | * @num_crtc: number of CRTCs on this device | 939 | * @num_crtc: number of CRTCs on this device |
756 | * @crtc_list: list of CRTC objects | 940 | * @crtc_list: list of CRTC objects |
941 | * @property_list: list of property objects | ||
757 | * @min_width: minimum pixel width on this device | 942 | * @min_width: minimum pixel width on this device |
758 | * @min_height: minimum pixel height on this device | 943 | * @min_height: minimum pixel height on this device |
759 | * @max_width: maximum pixel width on this device | 944 | * @max_width: maximum pixel width on this device |
760 | * @max_height: maximum pixel height on this device | 945 | * @max_height: maximum pixel height on this device |
761 | * @funcs: core driver provided mode setting functions | 946 | * @funcs: core driver provided mode setting functions |
762 | * @fb_base: base address of the framebuffer | 947 | * @fb_base: base address of the framebuffer |
763 | * @poll_enabled: track polling status for this device | 948 | * @poll_enabled: track polling support for this device |
949 | * @poll_running: track polling status for this device | ||
764 | * @output_poll_work: delayed work for polling in process context | 950 | * @output_poll_work: delayed work for polling in process context |
951 | * @property_blob_list: list of all the blob property objects | ||
765 | * @*_property: core property tracking | 952 | * @*_property: core property tracking |
953 | * @preferred_depth: preferred RBG pixel depth, used by fb helpers | ||
954 | * @prefer_shadow: hint to userspace to prefer shadow-fb rendering | ||
955 | * @async_page_flip: does this device support async flips on the primary plane? | ||
956 | * @cursor_width: hint to userspace for max cursor width | ||
957 | * @cursor_height: hint to userspace for max cursor height | ||
766 | * | 958 | * |
767 | * Core mode resource tracking structure. All CRTC, encoders, and connectors | 959 | * Core mode resource tracking structure. All CRTC, encoders, and connectors |
768 | * enumerated by the driver are added here, as are global properties. Some | 960 | * enumerated by the driver are added here, as are global properties. Some |
@@ -776,14 +968,7 @@ struct drm_mode_config { | |||
776 | struct idr crtc_idr; /* use this idr for all IDs, fb, crtc, connector, modes - just makes life easier */ | 968 | struct idr crtc_idr; /* use this idr for all IDs, fb, crtc, connector, modes - just makes life easier */ |
777 | /* this is limited to one for now */ | 969 | /* this is limited to one for now */ |
778 | 970 | ||
779 | 971 | struct mutex fb_lock; /* proctects global and per-file fb lists */ | |
780 | /** | ||
781 | * fb_lock - mutex to protect fb state | ||
782 | * | ||
783 | * Besides the global fb list his also protects the fbs list in the | ||
784 | * file_priv | ||
785 | */ | ||
786 | struct mutex fb_lock; | ||
787 | int num_fb; | 972 | int num_fb; |
788 | struct list_head fb_list; | 973 | struct list_head fb_list; |
789 | 974 | ||
@@ -880,9 +1065,6 @@ extern int drm_crtc_init_with_planes(struct drm_device *dev, | |||
880 | struct drm_plane *primary, | 1065 | struct drm_plane *primary, |
881 | struct drm_plane *cursor, | 1066 | struct drm_plane *cursor, |
882 | const struct drm_crtc_funcs *funcs); | 1067 | const struct drm_crtc_funcs *funcs); |
883 | extern int drm_crtc_init(struct drm_device *dev, | ||
884 | struct drm_crtc *crtc, | ||
885 | const struct drm_crtc_funcs *funcs); | ||
886 | extern void drm_crtc_cleanup(struct drm_crtc *crtc); | 1068 | extern void drm_crtc_cleanup(struct drm_crtc *crtc); |
887 | extern unsigned int drm_crtc_index(struct drm_crtc *crtc); | 1069 | extern unsigned int drm_crtc_index(struct drm_crtc *crtc); |
888 | 1070 | ||
diff --git a/include/drm/drm_crtc_helper.h b/include/drm/drm_crtc_helper.h index a3d75fefd010..7adbb65ea8ae 100644 --- a/include/drm/drm_crtc_helper.h +++ b/include/drm/drm_crtc_helper.h | |||
@@ -68,6 +68,7 @@ struct drm_crtc_helper_funcs { | |||
68 | int (*mode_set)(struct drm_crtc *crtc, struct drm_display_mode *mode, | 68 | int (*mode_set)(struct drm_crtc *crtc, struct drm_display_mode *mode, |
69 | struct drm_display_mode *adjusted_mode, int x, int y, | 69 | struct drm_display_mode *adjusted_mode, int x, int y, |
70 | struct drm_framebuffer *old_fb); | 70 | struct drm_framebuffer *old_fb); |
71 | void (*mode_set_nofb)(struct drm_crtc *crtc); | ||
71 | 72 | ||
72 | /* Move the crtc on the current fb to the given position *optional* */ | 73 | /* Move the crtc on the current fb to the given position *optional* */ |
73 | int (*mode_set_base)(struct drm_crtc *crtc, int x, int y, | 74 | int (*mode_set_base)(struct drm_crtc *crtc, int x, int y, |
@@ -81,6 +82,12 @@ struct drm_crtc_helper_funcs { | |||
81 | 82 | ||
82 | /* disable crtc when not in use - more explicit than dpms off */ | 83 | /* disable crtc when not in use - more explicit than dpms off */ |
83 | void (*disable)(struct drm_crtc *crtc); | 84 | void (*disable)(struct drm_crtc *crtc); |
85 | |||
86 | /* atomic helpers */ | ||
87 | int (*atomic_check)(struct drm_crtc *crtc, | ||
88 | struct drm_crtc_state *state); | ||
89 | void (*atomic_begin)(struct drm_crtc *crtc); | ||
90 | void (*atomic_flush)(struct drm_crtc *crtc); | ||
84 | }; | 91 | }; |
85 | 92 | ||
86 | /** | 93 | /** |
@@ -161,6 +168,12 @@ static inline void drm_connector_helper_add(struct drm_connector *connector, | |||
161 | 168 | ||
162 | extern void drm_helper_resume_force_mode(struct drm_device *dev); | 169 | extern void drm_helper_resume_force_mode(struct drm_device *dev); |
163 | 170 | ||
171 | int drm_helper_crtc_mode_set(struct drm_crtc *crtc, struct drm_display_mode *mode, | ||
172 | struct drm_display_mode *adjusted_mode, int x, int y, | ||
173 | struct drm_framebuffer *old_fb); | ||
174 | int drm_helper_crtc_mode_set_base(struct drm_crtc *crtc, int x, int y, | ||
175 | struct drm_framebuffer *old_fb); | ||
176 | |||
164 | /* drm_probe_helper.c */ | 177 | /* drm_probe_helper.c */ |
165 | extern int drm_helper_probe_single_connector_modes(struct drm_connector | 178 | extern int drm_helper_probe_single_connector_modes(struct drm_connector |
166 | *connector, uint32_t maxX, | 179 | *connector, uint32_t maxX, |
diff --git a/include/drm/drm_dp_helper.h b/include/drm/drm_dp_helper.h index 8edeed00c082..11f8c84f98ce 100644 --- a/include/drm/drm_dp_helper.h +++ b/include/drm/drm_dp_helper.h | |||
@@ -405,26 +405,6 @@ | |||
405 | #define MODE_I2C_READ 4 | 405 | #define MODE_I2C_READ 4 |
406 | #define MODE_I2C_STOP 8 | 406 | #define MODE_I2C_STOP 8 |
407 | 407 | ||
408 | /** | ||
409 | * struct i2c_algo_dp_aux_data - driver interface structure for i2c over dp | ||
410 | * aux algorithm | ||
411 | * @running: set by the algo indicating whether an i2c is ongoing or whether | ||
412 | * the i2c bus is quiescent | ||
413 | * @address: i2c target address for the currently ongoing transfer | ||
414 | * @aux_ch: driver callback to transfer a single byte of the i2c payload | ||
415 | */ | ||
416 | struct i2c_algo_dp_aux_data { | ||
417 | bool running; | ||
418 | u16 address; | ||
419 | int (*aux_ch) (struct i2c_adapter *adapter, | ||
420 | int mode, uint8_t write_byte, | ||
421 | uint8_t *read_byte); | ||
422 | }; | ||
423 | |||
424 | int | ||
425 | i2c_dp_aux_add_bus(struct i2c_adapter *adapter); | ||
426 | |||
427 | |||
428 | #define DP_LINK_STATUS_SIZE 6 | 408 | #define DP_LINK_STATUS_SIZE 6 |
429 | bool drm_dp_channel_eq_ok(const u8 link_status[DP_LINK_STATUS_SIZE], | 409 | bool drm_dp_channel_eq_ok(const u8 link_status[DP_LINK_STATUS_SIZE], |
430 | int lane_count); | 410 | int lane_count); |
@@ -551,6 +531,7 @@ struct drm_dp_aux { | |||
551 | struct mutex hw_mutex; | 531 | struct mutex hw_mutex; |
552 | ssize_t (*transfer)(struct drm_dp_aux *aux, | 532 | ssize_t (*transfer)(struct drm_dp_aux *aux, |
553 | struct drm_dp_aux_msg *msg); | 533 | struct drm_dp_aux_msg *msg); |
534 | unsigned i2c_nack_count, i2c_defer_count; | ||
554 | }; | 535 | }; |
555 | 536 | ||
556 | ssize_t drm_dp_dpcd_read(struct drm_dp_aux *aux, unsigned int offset, | 537 | ssize_t drm_dp_dpcd_read(struct drm_dp_aux *aux, unsigned int offset, |
diff --git a/include/drm/drm_dp_mst_helper.h b/include/drm/drm_dp_mst_helper.h index 338fc1053835..05e85ee10e74 100644 --- a/include/drm/drm_dp_mst_helper.h +++ b/include/drm/drm_dp_mst_helper.h | |||
@@ -28,7 +28,7 @@ | |||
28 | struct drm_dp_mst_branch; | 28 | struct drm_dp_mst_branch; |
29 | 29 | ||
30 | /** | 30 | /** |
31 | * struct drm_dp_vcpi - Virtual Channel Payload Identifer | 31 | * struct drm_dp_vcpi - Virtual Channel Payload Identifier |
32 | * @vcpi: Virtual channel ID. | 32 | * @vcpi: Virtual channel ID. |
33 | * @pbn: Payload Bandwidth Number for this channel | 33 | * @pbn: Payload Bandwidth Number for this channel |
34 | * @aligned_pbn: PBN aligned with slot size | 34 | * @aligned_pbn: PBN aligned with slot size |
diff --git a/include/drm/drm_edid.h b/include/drm/drm_edid.h index b96031d947a0..c2f1bfa22010 100644 --- a/include/drm/drm_edid.h +++ b/include/drm/drm_edid.h | |||
@@ -207,6 +207,61 @@ struct detailed_timing { | |||
207 | #define DRM_EDID_HDMI_DC_30 (1 << 4) | 207 | #define DRM_EDID_HDMI_DC_30 (1 << 4) |
208 | #define DRM_EDID_HDMI_DC_Y444 (1 << 3) | 208 | #define DRM_EDID_HDMI_DC_Y444 (1 << 3) |
209 | 209 | ||
210 | /* ELD Header Block */ | ||
211 | #define DRM_ELD_HEADER_BLOCK_SIZE 4 | ||
212 | |||
213 | #define DRM_ELD_VER 0 | ||
214 | # define DRM_ELD_VER_SHIFT 3 | ||
215 | # define DRM_ELD_VER_MASK (0x1f << 3) | ||
216 | |||
217 | #define DRM_ELD_BASELINE_ELD_LEN 2 /* in dwords! */ | ||
218 | |||
219 | /* ELD Baseline Block for ELD_Ver == 2 */ | ||
220 | #define DRM_ELD_CEA_EDID_VER_MNL 4 | ||
221 | # define DRM_ELD_CEA_EDID_VER_SHIFT 5 | ||
222 | # define DRM_ELD_CEA_EDID_VER_MASK (7 << 5) | ||
223 | # define DRM_ELD_CEA_EDID_VER_NONE (0 << 5) | ||
224 | # define DRM_ELD_CEA_EDID_VER_CEA861 (1 << 5) | ||
225 | # define DRM_ELD_CEA_EDID_VER_CEA861A (2 << 5) | ||
226 | # define DRM_ELD_CEA_EDID_VER_CEA861BCD (3 << 5) | ||
227 | # define DRM_ELD_MNL_SHIFT 0 | ||
228 | # define DRM_ELD_MNL_MASK (0x1f << 0) | ||
229 | |||
230 | #define DRM_ELD_SAD_COUNT_CONN_TYPE 5 | ||
231 | # define DRM_ELD_SAD_COUNT_SHIFT 4 | ||
232 | # define DRM_ELD_SAD_COUNT_MASK (0xf << 4) | ||
233 | # define DRM_ELD_CONN_TYPE_SHIFT 2 | ||
234 | # define DRM_ELD_CONN_TYPE_MASK (3 << 2) | ||
235 | # define DRM_ELD_CONN_TYPE_HDMI (0 << 2) | ||
236 | # define DRM_ELD_CONN_TYPE_DP (1 << 2) | ||
237 | # define DRM_ELD_SUPPORTS_AI (1 << 1) | ||
238 | # define DRM_ELD_SUPPORTS_HDCP (1 << 0) | ||
239 | |||
240 | #define DRM_ELD_AUD_SYNCH_DELAY 6 /* in units of 2 ms */ | ||
241 | # define DRM_ELD_AUD_SYNCH_DELAY_MAX 0xfa /* 500 ms */ | ||
242 | |||
243 | #define DRM_ELD_SPEAKER 7 | ||
244 | # define DRM_ELD_SPEAKER_RLRC (1 << 6) | ||
245 | # define DRM_ELD_SPEAKER_FLRC (1 << 5) | ||
246 | # define DRM_ELD_SPEAKER_RC (1 << 4) | ||
247 | # define DRM_ELD_SPEAKER_RLR (1 << 3) | ||
248 | # define DRM_ELD_SPEAKER_FC (1 << 2) | ||
249 | # define DRM_ELD_SPEAKER_LFE (1 << 1) | ||
250 | # define DRM_ELD_SPEAKER_FLR (1 << 0) | ||
251 | |||
252 | #define DRM_ELD_PORT_ID 8 /* offsets 8..15 inclusive */ | ||
253 | # define DRM_ELD_PORT_ID_LEN 8 | ||
254 | |||
255 | #define DRM_ELD_MANUFACTURER_NAME0 16 | ||
256 | #define DRM_ELD_MANUFACTURER_NAME1 17 | ||
257 | |||
258 | #define DRM_ELD_PRODUCT_CODE0 18 | ||
259 | #define DRM_ELD_PRODUCT_CODE1 19 | ||
260 | |||
261 | #define DRM_ELD_MONITOR_NAME_STRING 20 /* offsets 20..(20+mnl-1) inclusive */ | ||
262 | |||
263 | #define DRM_ELD_CEA_SAD(mnl, sad) (20 + (mnl) + 3 * (sad)) | ||
264 | |||
210 | struct edid { | 265 | struct edid { |
211 | u8 header[8]; | 266 | u8 header[8]; |
212 | /* Vendor & product info */ | 267 | /* Vendor & product info */ |
@@ -279,4 +334,51 @@ int | |||
279 | drm_hdmi_vendor_infoframe_from_display_mode(struct hdmi_vendor_infoframe *frame, | 334 | drm_hdmi_vendor_infoframe_from_display_mode(struct hdmi_vendor_infoframe *frame, |
280 | const struct drm_display_mode *mode); | 335 | const struct drm_display_mode *mode); |
281 | 336 | ||
337 | /** | ||
338 | * drm_eld_mnl - Get ELD monitor name length in bytes. | ||
339 | * @eld: pointer to an eld memory structure with mnl set | ||
340 | */ | ||
341 | static inline int drm_eld_mnl(const uint8_t *eld) | ||
342 | { | ||
343 | return (eld[DRM_ELD_CEA_EDID_VER_MNL] & DRM_ELD_MNL_MASK) >> DRM_ELD_MNL_SHIFT; | ||
344 | } | ||
345 | |||
346 | /** | ||
347 | * drm_eld_sad_count - Get ELD SAD count. | ||
348 | * @eld: pointer to an eld memory structure with sad_count set | ||
349 | */ | ||
350 | static inline int drm_eld_sad_count(const uint8_t *eld) | ||
351 | { | ||
352 | return (eld[DRM_ELD_SAD_COUNT_CONN_TYPE] & DRM_ELD_SAD_COUNT_MASK) >> | ||
353 | DRM_ELD_SAD_COUNT_SHIFT; | ||
354 | } | ||
355 | |||
356 | /** | ||
357 | * drm_eld_calc_baseline_block_size - Calculate baseline block size in bytes | ||
358 | * @eld: pointer to an eld memory structure with mnl and sad_count set | ||
359 | * | ||
360 | * This is a helper for determining the payload size of the baseline block, in | ||
361 | * bytes, for e.g. setting the Baseline_ELD_Len field in the ELD header block. | ||
362 | */ | ||
363 | static inline int drm_eld_calc_baseline_block_size(const uint8_t *eld) | ||
364 | { | ||
365 | return DRM_ELD_MONITOR_NAME_STRING - DRM_ELD_HEADER_BLOCK_SIZE + | ||
366 | drm_eld_mnl(eld) + drm_eld_sad_count(eld) * 3; | ||
367 | } | ||
368 | |||
369 | /** | ||
370 | * drm_eld_size - Get ELD size in bytes | ||
371 | * @eld: pointer to a complete eld memory structure | ||
372 | * | ||
373 | * The returned value does not include the vendor block. It's vendor specific, | ||
374 | * and comprises of the remaining bytes in the ELD memory buffer after | ||
375 | * drm_eld_size() bytes of header and baseline block. | ||
376 | * | ||
377 | * The returned value is guaranteed to be a multiple of 4. | ||
378 | */ | ||
379 | static inline int drm_eld_size(const uint8_t *eld) | ||
380 | { | ||
381 | return DRM_ELD_HEADER_BLOCK_SIZE + eld[DRM_ELD_BASELINE_ELD_LEN] * 4; | ||
382 | } | ||
383 | |||
282 | #endif /* __DRM_EDID_H__ */ | 384 | #endif /* __DRM_EDID_H__ */ |
diff --git a/include/drm/drm_modeset_lock.h b/include/drm/drm_modeset_lock.h index 75a5c45e21c7..28931a23d96c 100644 --- a/include/drm/drm_modeset_lock.h +++ b/include/drm/drm_modeset_lock.h | |||
@@ -33,6 +33,7 @@ struct drm_modeset_lock; | |||
33 | * @ww_ctx: base acquire ctx | 33 | * @ww_ctx: base acquire ctx |
34 | * @contended: used internally for -EDEADLK handling | 34 | * @contended: used internally for -EDEADLK handling |
35 | * @locked: list of held locks | 35 | * @locked: list of held locks |
36 | * @trylock_only: trylock mode used in atomic contexts/panic notifiers | ||
36 | * | 37 | * |
37 | * Each thread competing for a set of locks must use one acquire | 38 | * Each thread competing for a set of locks must use one acquire |
38 | * ctx. And if any lock fxn returns -EDEADLK, it must backoff and | 39 | * ctx. And if any lock fxn returns -EDEADLK, it must backoff and |
diff --git a/include/drm/drm_plane_helper.h b/include/drm/drm_plane_helper.h index 52e6870534b2..c48f14d88690 100644 --- a/include/drm/drm_plane_helper.h +++ b/include/drm/drm_plane_helper.h | |||
@@ -25,6 +25,7 @@ | |||
25 | #define DRM_PLANE_HELPER_H | 25 | #define DRM_PLANE_HELPER_H |
26 | 26 | ||
27 | #include <drm/drm_rect.h> | 27 | #include <drm/drm_rect.h> |
28 | #include <drm/drm_crtc.h> | ||
28 | 29 | ||
29 | /* | 30 | /* |
30 | * Drivers that don't allow primary plane scaling may pass this macro in place | 31 | * Drivers that don't allow primary plane scaling may pass this macro in place |
@@ -42,6 +43,32 @@ | |||
42 | * planes. | 43 | * planes. |
43 | */ | 44 | */ |
44 | 45 | ||
46 | extern int drm_crtc_init(struct drm_device *dev, | ||
47 | struct drm_crtc *crtc, | ||
48 | const struct drm_crtc_funcs *funcs); | ||
49 | |||
50 | /** | ||
51 | * drm_plane_helper_funcs - helper operations for CRTCs | ||
52 | * | ||
53 | * The helper operations are called by the mid-layer CRTC helper. | ||
54 | */ | ||
55 | struct drm_plane_helper_funcs { | ||
56 | int (*prepare_fb)(struct drm_plane *plane, | ||
57 | struct drm_framebuffer *fb); | ||
58 | void (*cleanup_fb)(struct drm_plane *plane, | ||
59 | struct drm_framebuffer *fb); | ||
60 | |||
61 | int (*atomic_check)(struct drm_plane *plane, | ||
62 | struct drm_plane_state *state); | ||
63 | void (*atomic_update)(struct drm_plane *plane); | ||
64 | }; | ||
65 | |||
66 | static inline void drm_plane_helper_add(struct drm_plane *plane, | ||
67 | const struct drm_plane_helper_funcs *funcs) | ||
68 | { | ||
69 | plane->helper_private = (void *)funcs; | ||
70 | } | ||
71 | |||
45 | extern int drm_plane_helper_check_update(struct drm_plane *plane, | 72 | extern int drm_plane_helper_check_update(struct drm_plane *plane, |
46 | struct drm_crtc *crtc, | 73 | struct drm_crtc *crtc, |
47 | struct drm_framebuffer *fb, | 74 | struct drm_framebuffer *fb, |
@@ -68,4 +95,16 @@ extern struct drm_plane *drm_primary_helper_create_plane(struct drm_device *dev, | |||
68 | int num_formats); | 95 | int num_formats); |
69 | 96 | ||
70 | 97 | ||
98 | int drm_plane_helper_update(struct drm_plane *plane, struct drm_crtc *crtc, | ||
99 | struct drm_framebuffer *fb, | ||
100 | int crtc_x, int crtc_y, | ||
101 | unsigned int crtc_w, unsigned int crtc_h, | ||
102 | uint32_t src_x, uint32_t src_y, | ||
103 | uint32_t src_w, uint32_t src_h); | ||
104 | int drm_plane_helper_disable(struct drm_plane *plane); | ||
105 | |||
106 | /* For use by drm_crtc_helper.c */ | ||
107 | int drm_plane_helper_commit(struct drm_plane *plane, | ||
108 | struct drm_plane_state *plane_state, | ||
109 | struct drm_framebuffer *old_fb); | ||
71 | #endif | 110 | #endif |