diff options
author | Dave Airlie <airlied@redhat.com> | 2016-08-23 17:11:48 -0400 |
---|---|---|
committer | Dave Airlie <airlied@redhat.com> | 2016-08-23 17:11:48 -0400 |
commit | d804819605b461280ca176d982ee3204721c698b (patch) | |
tree | b98d2ea943d337deb3c8d7683dc6e5b209dd2ea7 | |
parent | fc93ff608b15ae32cde3006b7af860b59cac20ec (diff) | |
parent | 28579f37467cd1a9130a6287cf8322986e0b56f9 (diff) |
Merge tag 'topic/drm-misc-2016-08-23' of git://anongit.freedesktop.org/drm-intel into drm-next
A few bigger things:
- start of splitting drm_crtc.c into more manageable and better documneted
chunks
- DRM_DEV_* logging (Sean)
* tag 'topic/drm-misc-2016-08-23' of git://anongit.freedesktop.org/drm-intel: (46 commits)
drm/fb-helper: Make docs for fb_set_suspend wrappers consistent
drm/rockchip: Delete unnecessary assignment for the field "owner"
drm/bridge: dw-hdmi: Delete unnecessary assignment for the field "owner"
drm/rockchip: Don't continue trying to enable crtc on failure
drm/fb-helper: Add drm_fb_helper_set_suspend_unlocked()
drm/fb-helper: Fix the dummy remove_conflicting_framebuffers
drm/udl: Ensure channel is selected before using the device.
drm: Avoid calling dev_printk(.dev = NULL)
drm: avoid exposing kernel stack in compat_drm_getstats
reservation: fix small comment typo
drm: Don't implement empty prepare_fb()/cleanup_fb()
virtio-gpu: Use memdup_user() rather than duplicating its implementation
GPU-DRM-Savage: Use memdup_user() rather than duplicating
drm: Allow drivers to modify plane_state in prepare_fb/cleanup_fb
drm/rockchip: Use DRM_DEV_ERROR in vop
drm: Introduce DRM_DEV_* log messages
drm/edid: CEA mode 64 1080p100 vsync pulse width incorrect
Revert "drm/hisilicon: Don't set drm_device->platformdev"
dma-buf: fix kernel-doc warning and typos
drm: Fix kerneldoc in drm_plane_helper.c
...
90 files changed, 4180 insertions, 3857 deletions
diff --git a/Documentation/gpu/drm-kms-helpers.rst b/Documentation/gpu/drm-kms-helpers.rst index 0b302fedf1af..59fa3c11efab 100644 --- a/Documentation/gpu/drm-kms-helpers.rst +++ b/Documentation/gpu/drm-kms-helpers.rst | |||
@@ -2,38 +2,45 @@ | |||
2 | Mode Setting Helper Functions | 2 | Mode Setting Helper Functions |
3 | ============================= | 3 | ============================= |
4 | 4 | ||
5 | The plane, CRTC, encoder and connector functions provided by the drivers | 5 | The DRM subsystem aims for a strong separation between core code and helper |
6 | implement the DRM API. They're called by the DRM core and ioctl handlers | 6 | libraries. Core code takes care of general setup and teardown and decoding |
7 | to handle device state changes and configuration request. As | 7 | userspace requests to kernel internal objects. Everything else is handled by a |
8 | implementing those functions often requires logic not specific to | 8 | large set of helper libraries, which can be combined freely to pick and choose |
9 | drivers, mid-layer helper functions are available to avoid duplicating | 9 | for each driver what fits, and avoid shared code where special behaviour is |
10 | boilerplate code. | 10 | needed. |
11 | 11 | ||
12 | The DRM core contains one mid-layer implementation. The mid-layer | 12 | This distinction between core code and helpers is especially strong in the |
13 | provides implementations of several plane, CRTC, encoder and connector | 13 | modesetting code, where there's a shared userspace ABI for all drivers. This is |
14 | functions (called from the top of the mid-layer) that pre-process | 14 | in contrast to the render side, where pretty much everything (with very few |
15 | requests and call lower-level functions provided by the driver (at the | 15 | exceptions) can be considered optional helper code. |
16 | bottom of the mid-layer). For instance, the | 16 | |
17 | :c:func:`drm_crtc_helper_set_config()` function can be used to | 17 | There are a few areas these helpers can grouped into: |
18 | fill the :c:type:`struct drm_crtc_funcs <drm_crtc_funcs>` | 18 | |
19 | set_config field. When called, it will split the set_config operation | 19 | * Helpers to implement modesetting. The important ones here are the atomic |
20 | in smaller, simpler operations and call the driver to handle them. | 20 | helpers. Old drivers still often use the legacy CRTC helpers. They both share |
21 | 21 | the same set of common helper vtables. For really simple drivers (anything | |
22 | To use the mid-layer, drivers call | 22 | that would have been a great fit in the deprecated fbdev subsystem) there's |
23 | :c:func:`drm_crtc_helper_add()`, | 23 | also the simple display pipe helpers. |
24 | :c:func:`drm_encoder_helper_add()` and | 24 | |
25 | :c:func:`drm_connector_helper_add()` functions to install their | 25 | * There's a big pile of helpers for handling outputs. First the generic bridge |
26 | mid-layer bottom operations handlers, and fill the :c:type:`struct | 26 | helpers for handling encoder and transcoder IP blocks. Second the panel helpers |
27 | drm_crtc_funcs <drm_crtc_funcs>`, :c:type:`struct | 27 | for handling panel-related information and logic. Plus then a big set of |
28 | drm_encoder_funcs <drm_encoder_funcs>` and :c:type:`struct | 28 | helpers for the various sink standards (DisplayPort, HDMI, MIPI DSI). Finally |
29 | drm_connector_funcs <drm_connector_funcs>` structures with | 29 | there's also generic helpers for handling output probing, and for dealing with |
30 | pointers to the mid-layer top API functions. Installing the mid-layer | 30 | EDIDs. |
31 | bottom operation handlers is best done right after registering the | 31 | |
32 | corresponding KMS object. | 32 | * The last group of helpers concerns itself with the frontend side of a display |
33 | 33 | pipeline: Planes, handling rectangles for visibility checking and scissoring, | |
34 | The mid-layer is not split between CRTC, encoder and connector | 34 | flip queues and assorted bits. |
35 | operations. To use it, a driver must provide bottom functions for all of | 35 | |
36 | the three KMS entities. | 36 | Modeset Helper Reference for Common Vtables |
37 | =========================================== | ||
38 | |||
39 | .. kernel-doc:: include/drm/drm_modeset_helper_vtables.h | ||
40 | :internal: | ||
41 | |||
42 | .. kernel-doc:: include/drm/drm_modeset_helper_vtables.h | ||
43 | :doc: overview | ||
37 | 44 | ||
38 | Atomic Modeset Helper Functions Reference | 45 | Atomic Modeset Helper Functions Reference |
39 | ========================================= | 46 | ========================================= |
@@ -62,33 +69,27 @@ Atomic State Reset and Initialization | |||
62 | .. kernel-doc:: drivers/gpu/drm/drm_atomic_helper.c | 69 | .. kernel-doc:: drivers/gpu/drm/drm_atomic_helper.c |
63 | :export: | 70 | :export: |
64 | 71 | ||
65 | Modeset Helper Reference for Common Vtables | ||
66 | =========================================== | ||
67 | |||
68 | .. kernel-doc:: include/drm/drm_modeset_helper_vtables.h | ||
69 | :internal: | ||
70 | |||
71 | .. kernel-doc:: include/drm/drm_modeset_helper_vtables.h | ||
72 | :doc: overview | ||
73 | |||
74 | Legacy CRTC/Modeset Helper Functions Reference | 72 | Legacy CRTC/Modeset Helper Functions Reference |
75 | ============================================== | 73 | ============================================== |
76 | 74 | ||
77 | .. kernel-doc:: drivers/gpu/drm/drm_crtc_helper.c | 75 | .. kernel-doc:: drivers/gpu/drm/drm_crtc_helper.c |
78 | :export: | 76 | :doc: overview |
79 | 77 | ||
80 | .. kernel-doc:: drivers/gpu/drm/drm_crtc_helper.c | 78 | .. kernel-doc:: drivers/gpu/drm/drm_crtc_helper.c |
81 | :doc: overview | 79 | :export: |
82 | 80 | ||
83 | Output Probing Helper Functions Reference | 81 | Simple KMS Helper Reference |
84 | ========================================= | 82 | =========================== |
85 | 83 | ||
86 | .. kernel-doc:: drivers/gpu/drm/drm_probe_helper.c | 84 | .. kernel-doc:: include/drm/drm_simple_kms_helper.h |
87 | :doc: output probing helper overview | 85 | :internal: |
88 | 86 | ||
89 | .. kernel-doc:: drivers/gpu/drm/drm_probe_helper.c | 87 | .. kernel-doc:: drivers/gpu/drm/drm_simple_kms_helper.c |
90 | :export: | 88 | :export: |
91 | 89 | ||
90 | .. kernel-doc:: drivers/gpu/drm/drm_simple_kms_helper.c | ||
91 | :doc: overview | ||
92 | |||
92 | fbdev Helper Functions Reference | 93 | fbdev Helper Functions Reference |
93 | ================================ | 94 | ================================ |
94 | 95 | ||
@@ -110,6 +111,36 @@ Framebuffer CMA Helper Functions Reference | |||
110 | .. kernel-doc:: drivers/gpu/drm/drm_fb_cma_helper.c | 111 | .. kernel-doc:: drivers/gpu/drm/drm_fb_cma_helper.c |
111 | :export: | 112 | :export: |
112 | 113 | ||
114 | Bridges | ||
115 | ======= | ||
116 | |||
117 | Overview | ||
118 | -------- | ||
119 | |||
120 | .. kernel-doc:: drivers/gpu/drm/drm_bridge.c | ||
121 | :doc: overview | ||
122 | |||
123 | Default bridge callback sequence | ||
124 | -------------------------------- | ||
125 | |||
126 | .. kernel-doc:: drivers/gpu/drm/drm_bridge.c | ||
127 | :doc: bridge callbacks | ||
128 | |||
129 | .. kernel-doc:: drivers/gpu/drm/drm_bridge.c | ||
130 | :export: | ||
131 | |||
132 | Panel Helper Reference | ||
133 | ====================== | ||
134 | |||
135 | .. kernel-doc:: include/drm/drm_panel.h | ||
136 | :internal: | ||
137 | |||
138 | .. kernel-doc:: drivers/gpu/drm/drm_panel.c | ||
139 | :export: | ||
140 | |||
141 | .. kernel-doc:: drivers/gpu/drm/drm_panel.c | ||
142 | :doc: drm panel | ||
143 | |||
113 | Display Port Helper Functions Reference | 144 | Display Port Helper Functions Reference |
114 | ======================================= | 145 | ======================================= |
115 | 146 | ||
@@ -158,6 +189,15 @@ MIPI DSI Helper Functions Reference | |||
158 | .. kernel-doc:: drivers/gpu/drm/drm_mipi_dsi.c | 189 | .. kernel-doc:: drivers/gpu/drm/drm_mipi_dsi.c |
159 | :export: | 190 | :export: |
160 | 191 | ||
192 | Output Probing Helper Functions Reference | ||
193 | ========================================= | ||
194 | |||
195 | .. kernel-doc:: drivers/gpu/drm/drm_probe_helper.c | ||
196 | :doc: output probing helper overview | ||
197 | |||
198 | .. kernel-doc:: drivers/gpu/drm/drm_probe_helper.c | ||
199 | :export: | ||
200 | |||
161 | EDID Helper Functions Reference | 201 | EDID Helper Functions Reference |
162 | =============================== | 202 | =============================== |
163 | 203 | ||
@@ -176,18 +216,6 @@ Rectangle Utilities Reference | |||
176 | .. kernel-doc:: drivers/gpu/drm/drm_rect.c | 216 | .. kernel-doc:: drivers/gpu/drm/drm_rect.c |
177 | :export: | 217 | :export: |
178 | 218 | ||
179 | Flip-work Helper Reference | ||
180 | ========================== | ||
181 | |||
182 | .. kernel-doc:: include/drm/drm_flip_work.h | ||
183 | :doc: flip utils | ||
184 | |||
185 | .. kernel-doc:: include/drm/drm_flip_work.h | ||
186 | :internal: | ||
187 | |||
188 | .. kernel-doc:: drivers/gpu/drm/drm_flip_work.c | ||
189 | :export: | ||
190 | |||
191 | HDMI Infoframes Helper Reference | 219 | HDMI Infoframes Helper Reference |
192 | ================================ | 220 | ================================ |
193 | 221 | ||
@@ -202,59 +230,40 @@ libraries and hence is also included here. | |||
202 | .. kernel-doc:: drivers/video/hdmi.c | 230 | .. kernel-doc:: drivers/video/hdmi.c |
203 | :export: | 231 | :export: |
204 | 232 | ||
205 | Plane Helper Reference | 233 | Flip-work Helper Reference |
206 | ====================== | 234 | ========================== |
207 | |||
208 | .. kernel-doc:: drivers/gpu/drm/drm_plane_helper.c | ||
209 | :export: | ||
210 | |||
211 | .. kernel-doc:: drivers/gpu/drm/drm_plane_helper.c | ||
212 | :doc: overview | ||
213 | 235 | ||
214 | Tile group | 236 | .. kernel-doc:: include/drm/drm_flip_work.h |
215 | ---------- | 237 | :doc: flip utils |
216 | 238 | ||
217 | .. kernel-doc:: drivers/gpu/drm/drm_crtc.c | 239 | .. kernel-doc:: include/drm/drm_flip_work.h |
218 | :doc: Tile group | 240 | :internal: |
219 | 241 | ||
220 | Bridges | 242 | .. kernel-doc:: drivers/gpu/drm/drm_flip_work.c |
221 | ======= | 243 | :export: |
222 | 244 | ||
223 | Overview | 245 | Plane Helper Reference |
224 | -------- | 246 | ====================== |
225 | 247 | ||
226 | .. kernel-doc:: drivers/gpu/drm/drm_bridge.c | 248 | .. kernel-doc:: drivers/gpu/drm/drm_plane_helper.c |
227 | :doc: overview | 249 | :doc: overview |
228 | 250 | ||
229 | Default bridge callback sequence | 251 | .. kernel-doc:: drivers/gpu/drm/drm_plane_helper.c |
230 | -------------------------------- | ||
231 | |||
232 | .. kernel-doc:: drivers/gpu/drm/drm_bridge.c | ||
233 | :doc: bridge callbacks | ||
234 | |||
235 | .. kernel-doc:: drivers/gpu/drm/drm_bridge.c | ||
236 | :export: | 252 | :export: |
237 | 253 | ||
238 | Panel Helper Reference | 254 | Tile group |
239 | ====================== | 255 | ========== |
240 | |||
241 | .. kernel-doc:: include/drm/drm_panel.h | ||
242 | :internal: | ||
243 | 256 | ||
244 | .. kernel-doc:: drivers/gpu/drm/drm_panel.c | 257 | # FIXME: This should probably be moved into a property documentation section |
245 | :export: | ||
246 | 258 | ||
247 | .. kernel-doc:: drivers/gpu/drm/drm_panel.c | 259 | .. kernel-doc:: drivers/gpu/drm/drm_crtc.c |
248 | :doc: drm panel | 260 | :doc: Tile group |
249 | 261 | ||
250 | Simple KMS Helper Reference | 262 | Auxiliary Modeset Helpers |
251 | =========================== | 263 | ========================= |
252 | 264 | ||
253 | .. kernel-doc:: include/drm/drm_simple_kms_helper.h | 265 | .. kernel-doc:: drivers/gpu/drm/drm_modeset_helper.c |
254 | :internal: | 266 | :doc: aux kms helpers |
255 | 267 | ||
256 | .. kernel-doc:: drivers/gpu/drm/drm_simple_kms_helper.c | 268 | .. kernel-doc:: drivers/gpu/drm/drm_modeset_helper.c |
257 | :export: | 269 | :export: |
258 | |||
259 | .. kernel-doc:: drivers/gpu/drm/drm_simple_kms_helper.c | ||
260 | :doc: overview | ||
diff --git a/Documentation/gpu/drm-kms.rst b/Documentation/gpu/drm-kms.rst index 8dfa4b214b96..fa948b4e029b 100644 --- a/Documentation/gpu/drm-kms.rst +++ b/Documentation/gpu/drm-kms.rst | |||
@@ -2,9 +2,6 @@ | |||
2 | Kernel Mode Setting (KMS) | 2 | Kernel Mode Setting (KMS) |
3 | ========================= | 3 | ========================= |
4 | 4 | ||
5 | Mode Setting | ||
6 | ============ | ||
7 | |||
8 | Drivers must initialize the mode setting core by calling | 5 | Drivers must initialize the mode setting core by calling |
9 | :c:func:`drm_mode_config_init()` on the DRM device. The function | 6 | :c:func:`drm_mode_config_init()` on the DRM device. The function |
10 | initializes the :c:type:`struct drm_device <drm_device>` | 7 | initializes the :c:type:`struct drm_device <drm_device>` |
@@ -18,60 +15,50 @@ be setup by initializing the following fields. | |||
18 | - struct drm_mode_config_funcs \*funcs; | 15 | - struct drm_mode_config_funcs \*funcs; |
19 | Mode setting functions. | 16 | Mode setting functions. |
20 | 17 | ||
21 | Display Modes Function Reference | 18 | KMS Data Structures |
22 | -------------------------------- | 19 | =================== |
23 | 20 | ||
24 | .. kernel-doc:: include/drm/drm_modes.h | 21 | .. kernel-doc:: include/drm/drm_crtc.h |
25 | :internal: | 22 | :internal: |
26 | 23 | ||
27 | .. kernel-doc:: drivers/gpu/drm/drm_modes.c | 24 | KMS API Functions |
25 | ================= | ||
26 | |||
27 | .. kernel-doc:: drivers/gpu/drm/drm_crtc.c | ||
28 | :export: | 28 | :export: |
29 | 29 | ||
30 | Atomic Mode Setting Function Reference | 30 | Atomic Mode Setting Function Reference |
31 | -------------------------------------- | 31 | ====================================== |
32 | 32 | ||
33 | .. kernel-doc:: drivers/gpu/drm/drm_atomic.c | 33 | .. kernel-doc:: drivers/gpu/drm/drm_atomic.c |
34 | :export: | 34 | :export: |
35 | 35 | ||
36 | .. kernel-doc:: drivers/gpu/drm/drm_atomic.c | 36 | .. kernel-doc:: include/drm/drm_atomic.h |
37 | :internal: | 37 | :internal: |
38 | 38 | ||
39 | Frame Buffer Abstraction | 39 | Frame Buffer Abstraction |
40 | ------------------------ | 40 | ======================== |
41 | 41 | ||
42 | Frame buffers are abstract memory objects that provide a source of | 42 | .. kernel-doc:: drivers/gpu/drm/drm_framebuffer.c |
43 | pixels to scanout to a CRTC. Applications explicitly request the | 43 | :doc: overview |
44 | creation of frame buffers through the DRM_IOCTL_MODE_ADDFB(2) ioctls | 44 | |
45 | and receive an opaque handle that can be passed to the KMS CRTC control, | 45 | Frame Buffer Functions Reference |
46 | plane configuration and page flip functions. | 46 | -------------------------------- |
47 | 47 | ||
48 | Frame buffers rely on the underneath memory manager for low-level memory | 48 | .. kernel-doc:: drivers/gpu/drm/drm_framebuffer.c |
49 | operations. When creating a frame buffer applications pass a memory | 49 | :export: |
50 | handle (or a list of memory handles for multi-planar formats) through | 50 | |
51 | the ``drm_mode_fb_cmd2`` argument. For drivers using GEM as their | 51 | .. kernel-doc:: include/drm/drm_framebuffer.h |
52 | userspace buffer management interface this would be a GEM handle. | 52 | :internal: |
53 | Drivers are however free to use their own backing storage object | ||
54 | handles, e.g. vmwgfx directly exposes special TTM handles to userspace | ||
55 | and so expects TTM handles in the create ioctl and not GEM handles. | ||
56 | |||
57 | The lifetime of a drm framebuffer is controlled with a reference count, | ||
58 | drivers can grab additional references with | ||
59 | :c:func:`drm_framebuffer_reference()`and drop them again with | ||
60 | :c:func:`drm_framebuffer_unreference()`. For driver-private | ||
61 | framebuffers for which the last reference is never dropped (e.g. for the | ||
62 | fbdev framebuffer when the struct :c:type:`struct drm_framebuffer | ||
63 | <drm_framebuffer>` is embedded into the fbdev helper struct) | ||
64 | drivers can manually clean up a framebuffer at module unload time with | ||
65 | :c:func:`drm_framebuffer_unregister_private()`. | ||
66 | 53 | ||
67 | DRM Format Handling | 54 | DRM Format Handling |
68 | ------------------- | 55 | =================== |
69 | 56 | ||
70 | .. kernel-doc:: drivers/gpu/drm/drm_fourcc.c | 57 | .. kernel-doc:: drivers/gpu/drm/drm_fourcc.c |
71 | :export: | 58 | :export: |
72 | 59 | ||
73 | Dumb Buffer Objects | 60 | Dumb Buffer Objects |
74 | ------------------- | 61 | =================== |
75 | 62 | ||
76 | The KMS API doesn't standardize backing storage object creation and | 63 | The KMS API doesn't standardize backing storage object creation and |
77 | leaves it to driver-specific ioctls. Furthermore actually creating a | 64 | leaves it to driver-specific ioctls. Furthermore actually creating a |
@@ -114,14 +101,29 @@ Note that dumb objects may not be used for gpu acceleration, as has been | |||
114 | attempted on some ARM embedded platforms. Such drivers really must have | 101 | attempted on some ARM embedded platforms. Such drivers really must have |
115 | a hardware-specific ioctl to allocate suitable buffer objects. | 102 | a hardware-specific ioctl to allocate suitable buffer objects. |
116 | 103 | ||
117 | Output Polling | 104 | Display Modes Function Reference |
118 | -------------- | 105 | ================================ |
106 | |||
107 | .. kernel-doc:: include/drm/drm_modes.h | ||
108 | :internal: | ||
109 | |||
110 | .. kernel-doc:: drivers/gpu/drm/drm_modes.c | ||
111 | :export: | ||
112 | |||
113 | Connector Abstraction | ||
114 | ===================== | ||
115 | |||
116 | .. kernel-doc:: drivers/gpu/drm/drm_connector.c | ||
117 | :doc: overview | ||
119 | 118 | ||
120 | void (\*output_poll_changed)(struct drm_device \*dev); | 119 | Connector Functions Reference |
121 | This operation notifies the driver that the status of one or more | 120 | ----------------------------- |
122 | connectors has changed. Drivers that use the fb helper can just call the | 121 | |
123 | :c:func:`drm_fb_helper_hotplug_event()` function to handle this | 122 | .. kernel-doc:: include/drm/drm_connector.h |
124 | operation. | 123 | :internal: |
124 | |||
125 | .. kernel-doc:: drivers/gpu/drm/drm_connector.c | ||
126 | :export: | ||
125 | 127 | ||
126 | KMS Initialization and Cleanup | 128 | KMS Initialization and Cleanup |
127 | ============================== | 129 | ============================== |
@@ -236,166 +238,6 @@ encoders unattached at initialization time. Applications (or the fbdev | |||
236 | compatibility layer when implemented) are responsible for attaching the | 238 | compatibility layer when implemented) are responsible for attaching the |
237 | encoders they want to use to a CRTC. | 239 | encoders they want to use to a CRTC. |
238 | 240 | ||
239 | Connectors (:c:type:`struct drm_connector <drm_connector>`) | ||
240 | ----------------------------------------------------------- | ||
241 | |||
242 | A connector is the final destination for pixel data on a device, and | ||
243 | usually connects directly to an external display device like a monitor | ||
244 | or laptop panel. A connector can only be attached to one encoder at a | ||
245 | time. The connector is also the structure where information about the | ||
246 | attached display is kept, so it contains fields for display data, EDID | ||
247 | data, DPMS & connection status, and information about modes supported on | ||
248 | the attached displays. | ||
249 | |||
250 | Connector Initialization | ||
251 | ~~~~~~~~~~~~~~~~~~~~~~~~ | ||
252 | |||
253 | Finally a KMS driver must create, initialize, register and attach at | ||
254 | least one :c:type:`struct drm_connector <drm_connector>` | ||
255 | instance. The instance is created as other KMS objects and initialized | ||
256 | by setting the following fields. | ||
257 | |||
258 | interlace_allowed | ||
259 | Whether the connector can handle interlaced modes. | ||
260 | |||
261 | doublescan_allowed | ||
262 | Whether the connector can handle doublescan. | ||
263 | |||
264 | display_info | ||
265 | Display information is filled from EDID information when a display | ||
266 | is detected. For non hot-pluggable displays such as flat panels in | ||
267 | embedded systems, the driver should initialize the | ||
268 | display_info.width_mm and display_info.height_mm fields with the | ||
269 | physical size of the display. | ||
270 | |||
271 | polled | ||
272 | Connector polling mode, a combination of | ||
273 | |||
274 | DRM_CONNECTOR_POLL_HPD | ||
275 | The connector generates hotplug events and doesn't need to be | ||
276 | periodically polled. The CONNECT and DISCONNECT flags must not | ||
277 | be set together with the HPD flag. | ||
278 | |||
279 | DRM_CONNECTOR_POLL_CONNECT | ||
280 | Periodically poll the connector for connection. | ||
281 | |||
282 | DRM_CONNECTOR_POLL_DISCONNECT | ||
283 | Periodically poll the connector for disconnection. | ||
284 | |||
285 | Set to 0 for connectors that don't support connection status | ||
286 | discovery. | ||
287 | |||
288 | The connector is then registered with a call to | ||
289 | :c:func:`drm_connector_init()` with a pointer to the connector | ||
290 | functions and a connector type, and exposed through sysfs with a call to | ||
291 | :c:func:`drm_connector_register()`. | ||
292 | |||
293 | Supported connector types are | ||
294 | |||
295 | - DRM_MODE_CONNECTOR_VGA | ||
296 | - DRM_MODE_CONNECTOR_DVII | ||
297 | - DRM_MODE_CONNECTOR_DVID | ||
298 | - DRM_MODE_CONNECTOR_DVIA | ||
299 | - DRM_MODE_CONNECTOR_Composite | ||
300 | - DRM_MODE_CONNECTOR_SVIDEO | ||
301 | - DRM_MODE_CONNECTOR_LVDS | ||
302 | - DRM_MODE_CONNECTOR_Component | ||
303 | - DRM_MODE_CONNECTOR_9PinDIN | ||
304 | - DRM_MODE_CONNECTOR_DisplayPort | ||
305 | - DRM_MODE_CONNECTOR_HDMIA | ||
306 | - DRM_MODE_CONNECTOR_HDMIB | ||
307 | - DRM_MODE_CONNECTOR_TV | ||
308 | - DRM_MODE_CONNECTOR_eDP | ||
309 | - DRM_MODE_CONNECTOR_VIRTUAL | ||
310 | |||
311 | Connectors must be attached to an encoder to be used. For devices that | ||
312 | map connectors to encoders 1:1, the connector should be attached at | ||
313 | initialization time with a call to | ||
314 | :c:func:`drm_mode_connector_attach_encoder()`. The driver must | ||
315 | also set the :c:type:`struct drm_connector <drm_connector>` | ||
316 | encoder field to point to the attached encoder. | ||
317 | |||
318 | Finally, drivers must initialize the connectors state change detection | ||
319 | with a call to :c:func:`drm_kms_helper_poll_init()`. If at least | ||
320 | one connector is pollable but can't generate hotplug interrupts | ||
321 | (indicated by the DRM_CONNECTOR_POLL_CONNECT and | ||
322 | DRM_CONNECTOR_POLL_DISCONNECT connector flags), a delayed work will | ||
323 | automatically be queued to periodically poll for changes. Connectors | ||
324 | that can generate hotplug interrupts must be marked with the | ||
325 | DRM_CONNECTOR_POLL_HPD flag instead, and their interrupt handler must | ||
326 | call :c:func:`drm_helper_hpd_irq_event()`. The function will | ||
327 | queue a delayed work to check the state of all connectors, but no | ||
328 | periodic polling will be done. | ||
329 | |||
330 | Connector Operations | ||
331 | ~~~~~~~~~~~~~~~~~~~~ | ||
332 | |||
333 | **Note** | ||
334 | |||
335 | Unless otherwise state, all operations are mandatory. | ||
336 | |||
337 | DPMS | ||
338 | '''' | ||
339 | |||
340 | void (\*dpms)(struct drm_connector \*connector, int mode); | ||
341 | The DPMS operation sets the power state of a connector. The mode | ||
342 | argument is one of | ||
343 | |||
344 | - DRM_MODE_DPMS_ON | ||
345 | |||
346 | - DRM_MODE_DPMS_STANDBY | ||
347 | |||
348 | - DRM_MODE_DPMS_SUSPEND | ||
349 | |||
350 | - DRM_MODE_DPMS_OFF | ||
351 | |||
352 | In all but DPMS_ON mode the encoder to which the connector is attached | ||
353 | should put the display in low-power mode by driving its signals | ||
354 | appropriately. If more than one connector is attached to the encoder | ||
355 | care should be taken not to change the power state of other displays as | ||
356 | a side effect. Low-power mode should be propagated to the encoders and | ||
357 | CRTCs when all related connectors are put in low-power mode. | ||
358 | |||
359 | Modes | ||
360 | ''''' | ||
361 | |||
362 | int (\*fill_modes)(struct drm_connector \*connector, uint32_t | ||
363 | max_width, uint32_t max_height); | ||
364 | Fill the mode list with all supported modes for the connector. If the | ||
365 | ``max_width`` and ``max_height`` arguments are non-zero, the | ||
366 | implementation must ignore all modes wider than ``max_width`` or higher | ||
367 | than ``max_height``. | ||
368 | |||
369 | The connector must also fill in this operation its display_info | ||
370 | width_mm and height_mm fields with the connected display physical size | ||
371 | in millimeters. The fields should be set to 0 if the value isn't known | ||
372 | or is not applicable (for instance for projector devices). | ||
373 | |||
374 | Connection Status | ||
375 | ''''''''''''''''' | ||
376 | |||
377 | The connection status is updated through polling or hotplug events when | ||
378 | supported (see ?). The status value is reported to userspace through | ||
379 | ioctls and must not be used inside the driver, as it only gets | ||
380 | initialized by a call to :c:func:`drm_mode_getconnector()` from | ||
381 | userspace. | ||
382 | |||
383 | enum drm_connector_status (\*detect)(struct drm_connector | ||
384 | \*connector, bool force); | ||
385 | Check to see if anything is attached to the connector. The ``force`` | ||
386 | parameter is set to false whilst polling or to true when checking the | ||
387 | connector due to user request. ``force`` can be used by the driver to | ||
388 | avoid expensive, destructive operations during automated probing. | ||
389 | |||
390 | Return connector_status_connected if something is connected to the | ||
391 | connector, connector_status_disconnected if nothing is connected and | ||
392 | connector_status_unknown if the connection state isn't known. | ||
393 | |||
394 | Drivers should only return connector_status_connected if the | ||
395 | connection status has really been probed as connected. Connectors that | ||
396 | can't detect the connection status, or failed connection status probes, | ||
397 | should return connector_status_unknown. | ||
398 | |||
399 | Cleanup | 241 | Cleanup |
400 | ------- | 242 | ------- |
401 | 243 | ||
@@ -463,20 +305,8 @@ created for fetching EDID data and performing monitor detection. Once | |||
463 | the process is complete, the new connector is registered with sysfs to | 305 | the process is complete, the new connector is registered with sysfs to |
464 | make its properties available to applications. | 306 | make its properties available to applications. |
465 | 307 | ||
466 | KMS API Functions | ||
467 | ----------------- | ||
468 | |||
469 | .. kernel-doc:: drivers/gpu/drm/drm_crtc.c | ||
470 | :export: | ||
471 | |||
472 | KMS Data Structures | ||
473 | ------------------- | ||
474 | |||
475 | .. kernel-doc:: include/drm/drm_crtc.h | ||
476 | :internal: | ||
477 | |||
478 | KMS Locking | 308 | KMS Locking |
479 | ----------- | 309 | =========== |
480 | 310 | ||
481 | .. kernel-doc:: drivers/gpu/drm/drm_modeset_lock.c | 311 | .. kernel-doc:: drivers/gpu/drm/drm_modeset_lock.c |
482 | :doc: kms locking | 312 | :doc: kms locking |
@@ -575,6 +405,12 @@ connector and plane objects by calling the | |||
575 | pointer to the target object, a pointer to the previously created | 405 | pointer to the target object, a pointer to the previously created |
576 | property and an initial instance value. | 406 | property and an initial instance value. |
577 | 407 | ||
408 | Blending and Z-Position properties | ||
409 | ---------------------------------- | ||
410 | |||
411 | .. kernel-doc:: drivers/gpu/drm/drm_blend.c | ||
412 | :export: | ||
413 | |||
578 | Existing KMS Properties | 414 | Existing KMS Properties |
579 | ----------------------- | 415 | ----------------------- |
580 | 416 | ||
diff --git a/Documentation/gpu/drm-mm.rst b/Documentation/gpu/drm-mm.rst index 59f9822fecd0..bca808535dfd 100644 --- a/Documentation/gpu/drm-mm.rst +++ b/Documentation/gpu/drm-mm.rst | |||
@@ -26,12 +26,12 @@ TTM, but has no video RAM management capabilities and is thus limited to | |||
26 | UMA devices. | 26 | UMA devices. |
27 | 27 | ||
28 | The Translation Table Manager (TTM) | 28 | The Translation Table Manager (TTM) |
29 | ----------------------------------- | 29 | =================================== |
30 | 30 | ||
31 | TTM design background and information belongs here. | 31 | TTM design background and information belongs here. |
32 | 32 | ||
33 | TTM initialization | 33 | TTM initialization |
34 | ~~~~~~~~~~~~~~~~~~ | 34 | ------------------ |
35 | 35 | ||
36 | **Warning** | 36 | **Warning** |
37 | 37 | ||
@@ -77,7 +77,7 @@ object, ttm_global_item_ref() is used to create an initial reference | |||
77 | count for the TTM, which will call your initialization function. | 77 | count for the TTM, which will call your initialization function. |
78 | 78 | ||
79 | The Graphics Execution Manager (GEM) | 79 | The Graphics Execution Manager (GEM) |
80 | ------------------------------------ | 80 | ==================================== |
81 | 81 | ||
82 | The GEM design approach has resulted in a memory manager that doesn't | 82 | The GEM design approach has resulted in a memory manager that doesn't |
83 | provide full coverage of all (or even all common) use cases in its | 83 | provide full coverage of all (or even all common) use cases in its |
@@ -114,7 +114,7 @@ read & write, mapping, and domain ownership transfers are left to | |||
114 | driver-specific ioctls. | 114 | driver-specific ioctls. |
115 | 115 | ||
116 | GEM Initialization | 116 | GEM Initialization |
117 | ~~~~~~~~~~~~~~~~~~ | 117 | ------------------ |
118 | 118 | ||
119 | Drivers that use GEM must set the DRIVER_GEM bit in the struct | 119 | Drivers that use GEM must set the DRIVER_GEM bit in the struct |
120 | :c:type:`struct drm_driver <drm_driver>` driver_features | 120 | :c:type:`struct drm_driver <drm_driver>` driver_features |
@@ -132,7 +132,7 @@ typically not managed by GEM, and must be initialized separately into | |||
132 | its own DRM MM object. | 132 | its own DRM MM object. |
133 | 133 | ||
134 | GEM Objects Creation | 134 | GEM Objects Creation |
135 | ~~~~~~~~~~~~~~~~~~~~ | 135 | -------------------- |
136 | 136 | ||
137 | GEM splits creation of GEM objects and allocation of the memory that | 137 | GEM splits creation of GEM objects and allocation of the memory that |
138 | backs them in two distinct operations. | 138 | backs them in two distinct operations. |
@@ -173,7 +173,7 @@ a call to :c:func:`drm_gem_private_object_init()` instead of | |||
173 | must be managed by drivers. | 173 | must be managed by drivers. |
174 | 174 | ||
175 | GEM Objects Lifetime | 175 | GEM Objects Lifetime |
176 | ~~~~~~~~~~~~~~~~~~~~ | 176 | -------------------- |
177 | 177 | ||
178 | All GEM objects are reference-counted by the GEM core. References can be | 178 | All GEM objects are reference-counted by the GEM core. References can be |
179 | acquired and release by :c:func:`calling | 179 | acquired and release by :c:func:`calling |
@@ -196,7 +196,7 @@ resources created by the GEM core, which need to be released with | |||
196 | :c:func:`drm_gem_object_release()`. | 196 | :c:func:`drm_gem_object_release()`. |
197 | 197 | ||
198 | GEM Objects Naming | 198 | GEM Objects Naming |
199 | ~~~~~~~~~~~~~~~~~~ | 199 | ------------------ |
200 | 200 | ||
201 | Communication between userspace and the kernel refers to GEM objects | 201 | Communication between userspace and the kernel refers to GEM objects |
202 | using local handles, global names or, more recently, file descriptors. | 202 | using local handles, global names or, more recently, file descriptors. |
@@ -245,7 +245,7 @@ Furthermore PRIME also allows cross-device buffer sharing since it is | |||
245 | based on dma-bufs. | 245 | based on dma-bufs. |
246 | 246 | ||
247 | GEM Objects Mapping | 247 | GEM Objects Mapping |
248 | ~~~~~~~~~~~~~~~~~~~ | 248 | ------------------- |
249 | 249 | ||
250 | Because mapping operations are fairly heavyweight GEM favours | 250 | Because mapping operations are fairly heavyweight GEM favours |
251 | read/write-like access to buffers, implemented through driver-specific | 251 | read/write-like access to buffers, implemented through driver-specific |
@@ -304,7 +304,7 @@ Drivers that want to map the GEM object upfront instead of handling page | |||
304 | faults can implement their own mmap file operation handler. | 304 | faults can implement their own mmap file operation handler. |
305 | 305 | ||
306 | Memory Coherency | 306 | Memory Coherency |
307 | ~~~~~~~~~~~~~~~~ | 307 | ---------------- |
308 | 308 | ||
309 | When mapped to the device or used in a command buffer, backing pages for | 309 | When mapped to the device or used in a command buffer, backing pages for |
310 | an object are flushed to memory and marked write combined so as to be | 310 | an object are flushed to memory and marked write combined so as to be |
@@ -320,7 +320,7 @@ blocks the client and waits for rendering to complete before performing | |||
320 | any necessary flushing operations). | 320 | any necessary flushing operations). |
321 | 321 | ||
322 | Command Execution | 322 | Command Execution |
323 | ~~~~~~~~~~~~~~~~~ | 323 | ----------------- |
324 | 324 | ||
325 | Perhaps the most important GEM function for GPU devices is providing a | 325 | Perhaps the most important GEM function for GPU devices is providing a |
326 | command execution interface to clients. Client programs construct | 326 | command execution interface to clients. Client programs construct |
@@ -348,8 +348,20 @@ GEM Function Reference | |||
348 | .. kernel-doc:: include/drm/drm_gem.h | 348 | .. kernel-doc:: include/drm/drm_gem.h |
349 | :internal: | 349 | :internal: |
350 | 350 | ||
351 | GEM CMA Helper Functions Reference | ||
352 | ---------------------------------- | ||
353 | |||
354 | .. kernel-doc:: drivers/gpu/drm/drm_gem_cma_helper.c | ||
355 | :doc: cma helpers | ||
356 | |||
357 | .. kernel-doc:: drivers/gpu/drm/drm_gem_cma_helper.c | ||
358 | :export: | ||
359 | |||
360 | .. kernel-doc:: include/drm/drm_gem_cma_helper.h | ||
361 | :internal: | ||
362 | |||
351 | VMA Offset Manager | 363 | VMA Offset Manager |
352 | ------------------ | 364 | ================== |
353 | 365 | ||
354 | .. kernel-doc:: drivers/gpu/drm/drm_vma_manager.c | 366 | .. kernel-doc:: drivers/gpu/drm/drm_vma_manager.c |
355 | :doc: vma offset manager | 367 | :doc: vma offset manager |
@@ -361,14 +373,14 @@ VMA Offset Manager | |||
361 | :internal: | 373 | :internal: |
362 | 374 | ||
363 | PRIME Buffer Sharing | 375 | PRIME Buffer Sharing |
364 | -------------------- | 376 | ==================== |
365 | 377 | ||
366 | PRIME is the cross device buffer sharing framework in drm, originally | 378 | PRIME is the cross device buffer sharing framework in drm, originally |
367 | created for the OPTIMUS range of multi-gpu platforms. To userspace PRIME | 379 | created for the OPTIMUS range of multi-gpu platforms. To userspace PRIME |
368 | buffers are dma-buf based file descriptors. | 380 | buffers are dma-buf based file descriptors. |
369 | 381 | ||
370 | Overview and Driver Interface | 382 | Overview and Driver Interface |
371 | ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ | 383 | ----------------------------- |
372 | 384 | ||
373 | Similar to GEM global names, PRIME file descriptors are also used to | 385 | Similar to GEM global names, PRIME file descriptors are also used to |
374 | share buffer objects across processes. They offer additional security: | 386 | share buffer objects across processes. They offer additional security: |
@@ -406,7 +418,7 @@ struct drm_gem_object \*obj, int flags); struct drm_gem_object \* | |||
406 | support PRIME. | 418 | support PRIME. |
407 | 419 | ||
408 | PRIME Helper Functions | 420 | PRIME Helper Functions |
409 | ~~~~~~~~~~~~~~~~~~~~~~ | 421 | ---------------------- |
410 | 422 | ||
411 | .. kernel-doc:: drivers/gpu/drm/drm_prime.c | 423 | .. kernel-doc:: drivers/gpu/drm/drm_prime.c |
412 | :doc: PRIME Helpers | 424 | :doc: PRIME Helpers |
@@ -418,16 +430,16 @@ PRIME Function References | |||
418 | :export: | 430 | :export: |
419 | 431 | ||
420 | DRM MM Range Allocator | 432 | DRM MM Range Allocator |
421 | ---------------------- | 433 | ====================== |
422 | 434 | ||
423 | Overview | 435 | Overview |
424 | ~~~~~~~~ | 436 | -------- |
425 | 437 | ||
426 | .. kernel-doc:: drivers/gpu/drm/drm_mm.c | 438 | .. kernel-doc:: drivers/gpu/drm/drm_mm.c |
427 | :doc: Overview | 439 | :doc: Overview |
428 | 440 | ||
429 | LRU Scan/Eviction Support | 441 | LRU Scan/Eviction Support |
430 | ~~~~~~~~~~~~~~~~~~~~~~~~~ | 442 | ------------------------- |
431 | 443 | ||
432 | .. kernel-doc:: drivers/gpu/drm/drm_mm.c | 444 | .. kernel-doc:: drivers/gpu/drm/drm_mm.c |
433 | :doc: lru scan roaster | 445 | :doc: lru scan roaster |
@@ -440,15 +452,3 @@ DRM MM Range Allocator Function References | |||
440 | 452 | ||
441 | .. kernel-doc:: include/drm/drm_mm.h | 453 | .. kernel-doc:: include/drm/drm_mm.h |
442 | :internal: | 454 | :internal: |
443 | |||
444 | CMA Helper Functions Reference | ||
445 | ------------------------------ | ||
446 | |||
447 | .. kernel-doc:: drivers/gpu/drm/drm_gem_cma_helper.c | ||
448 | :doc: cma helpers | ||
449 | |||
450 | .. kernel-doc:: drivers/gpu/drm/drm_gem_cma_helper.c | ||
451 | :export: | ||
452 | |||
453 | .. kernel-doc:: include/drm/drm_gem_cma_helper.h | ||
454 | :internal: | ||
diff --git a/Documentation/gpu/drm-uapi.rst b/Documentation/gpu/drm-uapi.rst index 536bf3eaadd4..94876938aef3 100644 --- a/Documentation/gpu/drm-uapi.rst +++ b/Documentation/gpu/drm-uapi.rst | |||
@@ -33,6 +33,9 @@ Primary Nodes, DRM Master and Authentication | |||
33 | .. kernel-doc:: include/drm/drm_auth.h | 33 | .. kernel-doc:: include/drm/drm_auth.h |
34 | :internal: | 34 | :internal: |
35 | 35 | ||
36 | Open-Source Userspace Requirements | ||
37 | ================================== | ||
38 | |||
36 | Render nodes | 39 | Render nodes |
37 | ============ | 40 | ============ |
38 | 41 | ||
diff --git a/Documentation/gpu/index.rst b/Documentation/gpu/index.rst index fcac0fa72056..ba92f45abb76 100644 --- a/Documentation/gpu/index.rst +++ b/Documentation/gpu/index.rst | |||
@@ -12,3 +12,4 @@ Linux GPU Driver Developer's Guide | |||
12 | drm-uapi | 12 | drm-uapi |
13 | i915 | 13 | i915 |
14 | vga-switcheroo | 14 | vga-switcheroo |
15 | vgaarbiter | ||
diff --git a/Documentation/gpu/vga-switcheroo.rst b/Documentation/gpu/vga-switcheroo.rst index cbbdb994f1dd..463a74fc40d1 100644 --- a/Documentation/gpu/vga-switcheroo.rst +++ b/Documentation/gpu/vga-switcheroo.rst | |||
@@ -1,5 +1,3 @@ | |||
1 | .. _vga_switcheroo: | ||
2 | |||
3 | ============== | 1 | ============== |
4 | VGA Switcheroo | 2 | VGA Switcheroo |
5 | ============== | 3 | ============== |
diff --git a/Documentation/vgaarbiter.txt b/Documentation/gpu/vgaarbiter.rst index 014423e2824c..0b41b051d021 100644 --- a/Documentation/vgaarbiter.txt +++ b/Documentation/gpu/vgaarbiter.rst | |||
@@ -1,4 +1,4 @@ | |||
1 | 1 | =========== | |
2 | VGA Arbiter | 2 | VGA Arbiter |
3 | =========== | 3 | =========== |
4 | 4 | ||
@@ -19,21 +19,8 @@ control bus resources. Therefore an arbitration scheme outside of the X server | |||
19 | is needed to control the sharing of these resources. This document introduces | 19 | is needed to control the sharing of these resources. This document introduces |
20 | the operation of the VGA arbiter implemented for the Linux kernel. | 20 | the operation of the VGA arbiter implemented for the Linux kernel. |
21 | 21 | ||
22 | ---------------------------------------------------------------------------- | 22 | vgaarb kernel/userspace ABI |
23 | 23 | --------------------------- | |
24 | I. Details and Theory of Operation | ||
25 | I.1 vgaarb | ||
26 | I.2 libpciaccess | ||
27 | I.3 xf86VGAArbiter (X server implementation) | ||
28 | II. Credits | ||
29 | III.References | ||
30 | |||
31 | |||
32 | I. Details and Theory of Operation | ||
33 | ================================== | ||
34 | |||
35 | I.1 vgaarb | ||
36 | ---------- | ||
37 | 24 | ||
38 | The vgaarb is a module of the Linux Kernel. When it is initially loaded, it | 25 | The vgaarb is a module of the Linux Kernel. When it is initially loaded, it |
39 | scans all PCI devices and adds the VGA ones inside the arbitration. The | 26 | scans all PCI devices and adds the VGA ones inside the arbitration. The |
@@ -44,42 +31,52 @@ explicitly tell it by calling vga_set_legacy_decoding(). | |||
44 | The kernel exports a char device interface (/dev/vga_arbiter) to the clients, | 31 | The kernel exports a char device interface (/dev/vga_arbiter) to the clients, |
45 | which has the following semantics: | 32 | which has the following semantics: |
46 | 33 | ||
47 | open : open user instance of the arbiter. By default, it's attached to | 34 | open |
48 | the default VGA device of the system. | 35 | Opens a user instance of the arbiter. By default, it's attached to the |
49 | 36 | default VGA device of the system. | |
50 | close : close user instance. Release locks made by the user | 37 | |
51 | 38 | close | |
52 | read : return a string indicating the status of the target like: | 39 | Close a user instance. Release locks made by the user |
53 | 40 | ||
54 | "<card_ID>,decodes=<io_state>,owns=<io_state>,locks=<io_state> (ic,mc)" | 41 | read |
55 | 42 | Return a string indicating the status of the target like: | |
56 | An IO state string is of the form {io,mem,io+mem,none}, mc and | 43 | |
57 | ic are respectively mem and io lock counts (for debugging/ | 44 | "<card_ID>,decodes=<io_state>,owns=<io_state>,locks=<io_state> (ic,mc)" |
58 | diagnostic only). "decodes" indicate what the card currently | 45 | |
59 | decodes, "owns" indicates what is currently enabled on it, and | 46 | An IO state string is of the form {io,mem,io+mem,none}, mc and |
60 | "locks" indicates what is locked by this card. If the card is | 47 | ic are respectively mem and io lock counts (for debugging/ |
61 | unplugged, we get "invalid" then for card_ID and an -ENODEV | 48 | diagnostic only). "decodes" indicate what the card currently |
62 | error is returned for any command until a new card is targeted. | 49 | decodes, "owns" indicates what is currently enabled on it, and |
63 | 50 | "locks" indicates what is locked by this card. If the card is | |
64 | 51 | unplugged, we get "invalid" then for card_ID and an -ENODEV | |
65 | write : write a command to the arbiter. List of commands: | 52 | error is returned for any command until a new card is targeted. |
66 | 53 | ||
67 | target <card_ID> : switch target to card <card_ID> (see below) | 54 | |
68 | lock <io_state> : acquires locks on target ("none" is an invalid io_state) | 55 | write |
69 | trylock <io_state> : non-blocking acquire locks on target (returns EBUSY if | 56 | Write a command to the arbiter. List of commands: |
70 | unsuccessful) | 57 | |
71 | unlock <io_state> : release locks on target | 58 | target <card_ID> |
72 | unlock all : release all locks on target held by this user (not | 59 | switch target to card <card_ID> (see below) |
73 | implemented yet) | 60 | lock <io_state> |
74 | decodes <io_state> : set the legacy decoding attributes for the card | 61 | acquires locks on target ("none" is an invalid io_state) |
75 | 62 | trylock <io_state> | |
76 | poll : event if something changes on any card (not just the | 63 | non-blocking acquire locks on target (returns EBUSY if |
77 | target) | 64 | unsuccessful) |
78 | 65 | unlock <io_state> | |
79 | card_ID is of the form "PCI:domain:bus:dev.fn". It can be set to "default" | 66 | release locks on target |
80 | to go back to the system default card (TODO: not implemented yet). Currently, | 67 | unlock all |
81 | only PCI is supported as a prefix, but the userland API may support other bus | 68 | release all locks on target held by this user (not implemented |
82 | types in the future, even if the current kernel implementation doesn't. | 69 | yet) |
70 | decodes <io_state> | ||
71 | set the legacy decoding attributes for the card | ||
72 | |||
73 | poll | ||
74 | event if something changes on any card (not just the target) | ||
75 | |||
76 | card_ID is of the form "PCI:domain:bus:dev.fn". It can be set to "default" | ||
77 | to go back to the system default card (TODO: not implemented yet). Currently, | ||
78 | only PCI is supported as a prefix, but the userland API may support other bus | ||
79 | types in the future, even if the current kernel implementation doesn't. | ||
83 | 80 | ||
84 | Note about locks: | 81 | Note about locks: |
85 | 82 | ||
@@ -97,29 +94,35 @@ in the arbiter. | |||
97 | There is also an in-kernel API of the arbiter in case DRM, vgacon, or other | 94 | There is also an in-kernel API of the arbiter in case DRM, vgacon, or other |
98 | drivers want to use it. | 95 | drivers want to use it. |
99 | 96 | ||
97 | In-kernel interface | ||
98 | ------------------- | ||
99 | |||
100 | .. kernel-doc:: include/linux/vgaarb.h | ||
101 | :internal: | ||
100 | 102 | ||
101 | I.2 libpciaccess | 103 | .. kernel-doc:: drivers/gpu/vga/vgaarb.c |
102 | ---------------- | 104 | :export: |
105 | |||
106 | libpciaccess | ||
107 | ------------ | ||
103 | 108 | ||
104 | To use the vga arbiter char device it was implemented an API inside the | 109 | To use the vga arbiter char device it was implemented an API inside the |
105 | libpciaccess library. One field was added to struct pci_device (each device | 110 | libpciaccess library. One field was added to struct pci_device (each device |
106 | on the system): | 111 | on the system):: |
107 | 112 | ||
108 | /* the type of resource decoded by the device */ | 113 | /* the type of resource decoded by the device */ |
109 | int vgaarb_rsrc; | 114 | int vgaarb_rsrc; |
110 | 115 | ||
111 | Besides it, in pci_system were added: | 116 | Besides it, in pci_system were added:: |
112 | 117 | ||
113 | int vgaarb_fd; | 118 | int vgaarb_fd; |
114 | int vga_count; | 119 | int vga_count; |
115 | struct pci_device *vga_target; | 120 | struct pci_device *vga_target; |
116 | struct pci_device *vga_default_dev; | 121 | struct pci_device *vga_default_dev; |
117 | 122 | ||
118 | |||
119 | The vga_count is used to track how many cards are being arbitrated, so for | 123 | The vga_count is used to track how many cards are being arbitrated, so for |
120 | instance, if there is only one card, then it can completely escape arbitration. | 124 | instance, if there is only one card, then it can completely escape arbitration. |
121 | 125 | ||
122 | |||
123 | These functions below acquire VGA resources for the given card and mark those | 126 | These functions below acquire VGA resources for the given card and mark those |
124 | resources as locked. If the resources requested are "normal" (and not legacy) | 127 | resources as locked. If the resources requested are "normal" (and not legacy) |
125 | resources, the arbiter will first check whether the card is doing legacy | 128 | resources, the arbiter will first check whether the card is doing legacy |
@@ -136,44 +139,44 @@ VGA memory and IO afaik). If the card already owns the resources, the function | |||
136 | succeeds. vga_arb_trylock() will return (-EBUSY) instead of blocking. Nested | 139 | succeeds. vga_arb_trylock() will return (-EBUSY) instead of blocking. Nested |
137 | calls are supported (a per-resource counter is maintained). | 140 | calls are supported (a per-resource counter is maintained). |
138 | 141 | ||
142 | Set the target device of this client. :: | ||
139 | 143 | ||
140 | Set the target device of this client. | ||
141 | int pci_device_vgaarb_set_target (struct pci_device *dev); | 144 | int pci_device_vgaarb_set_target (struct pci_device *dev); |
142 | 145 | ||
143 | |||
144 | For instance, in x86 if two devices on the same bus want to lock different | 146 | For instance, in x86 if two devices on the same bus want to lock different |
145 | resources, both will succeed (lock). If devices are in different buses and | 147 | resources, both will succeed (lock). If devices are in different buses and |
146 | trying to lock different resources, only the first who tried succeeds. | 148 | trying to lock different resources, only the first who tried succeeds. :: |
149 | |||
147 | int pci_device_vgaarb_lock (void); | 150 | int pci_device_vgaarb_lock (void); |
148 | int pci_device_vgaarb_trylock (void); | 151 | int pci_device_vgaarb_trylock (void); |
149 | 152 | ||
150 | Unlock resources of device. | 153 | Unlock resources of device. :: |
154 | |||
151 | int pci_device_vgaarb_unlock (void); | 155 | int pci_device_vgaarb_unlock (void); |
152 | 156 | ||
153 | Indicates to the arbiter if the card decodes legacy VGA IOs, legacy VGA | 157 | Indicates to the arbiter if the card decodes legacy VGA IOs, legacy VGA |
154 | Memory, both, or none. All cards default to both, the card driver (fbdev for | 158 | Memory, both, or none. All cards default to both, the card driver (fbdev for |
155 | example) should tell the arbiter if it has disabled legacy decoding, so the | 159 | example) should tell the arbiter if it has disabled legacy decoding, so the |
156 | card can be left out of the arbitration process (and can be safe to take | 160 | card can be left out of the arbitration process (and can be safe to take |
157 | interrupts at any time. | 161 | interrupts at any time. :: |
162 | |||
158 | int pci_device_vgaarb_decodes (int new_vgaarb_rsrc); | 163 | int pci_device_vgaarb_decodes (int new_vgaarb_rsrc); |
159 | 164 | ||
160 | Connects to the arbiter device, allocates the struct | 165 | Connects to the arbiter device, allocates the struct :: |
161 | int pci_device_vgaarb_init (void); | ||
162 | 166 | ||
163 | Close the connection | 167 | int pci_device_vgaarb_init (void); |
164 | void pci_device_vgaarb_fini (void); | ||
165 | 168 | ||
169 | Close the connection :: | ||
166 | 170 | ||
167 | I.3 xf86VGAArbiter (X server implementation) | 171 | void pci_device_vgaarb_fini (void); |
168 | -------------------------------------------- | ||
169 | 172 | ||
170 | (TODO) | 173 | xf86VGAArbiter (X server implementation) |
174 | ---------------------------------------- | ||
171 | 175 | ||
172 | X server basically wraps all the functions that touch VGA registers somehow. | 176 | X server basically wraps all the functions that touch VGA registers somehow. |
173 | 177 | ||
174 | 178 | References | |
175 | II. Credits | 179 | ---------- |
176 | =========== | ||
177 | 180 | ||
178 | Benjamin Herrenschmidt (IBM?) started this work when he discussed such design | 181 | Benjamin Herrenschmidt (IBM?) started this work when he discussed such design |
179 | with the Xorg community in 2005 [1, 2]. In the end of 2007, Paulo Zanoni and | 182 | with the Xorg community in 2005 [1, 2]. In the end of 2007, Paulo Zanoni and |
@@ -182,11 +185,7 @@ enhancing the kernel code to adapt as a kernel module and also did the | |||
182 | implementation of the user space side [3]. Now (2009) Tiago Vignatti and Dave | 185 | implementation of the user space side [3]. Now (2009) Tiago Vignatti and Dave |
183 | Airlie finally put this work in shape and queued to Jesse Barnes' PCI tree. | 186 | Airlie finally put this work in shape and queued to Jesse Barnes' PCI tree. |
184 | 187 | ||
185 | 188 | 0) http://cgit.freedesktop.org/xorg/xserver/commit/?id=4b42448a2388d40f257774fbffdccaea87bd0347 | |
186 | III. References | 189 | 1) http://lists.freedesktop.org/archives/xorg/2005-March/006663.html |
187 | ============== | 190 | 2) http://lists.freedesktop.org/archives/xorg/2005-March/006745.html |
188 | 191 | 3) http://lists.freedesktop.org/archives/xorg/2007-October/029507.html | |
189 | [0] http://cgit.freedesktop.org/xorg/xserver/commit/?id=4b42448a2388d40f257774fbffdccaea87bd0347 | ||
190 | [1] http://lists.freedesktop.org/archives/xorg/2005-March/006663.html | ||
191 | [2] http://lists.freedesktop.org/archives/xorg/2005-March/006745.html | ||
192 | [3] http://lists.freedesktop.org/archives/xorg/2007-October/029507.html | ||
diff --git a/drivers/dma-buf/dma-buf.c b/drivers/dma-buf/dma-buf.c index ddaee60ae52a..cf04d249a6a4 100644 --- a/drivers/dma-buf/dma-buf.c +++ b/drivers/dma-buf/dma-buf.c | |||
@@ -586,6 +586,22 @@ void dma_buf_unmap_attachment(struct dma_buf_attachment *attach, | |||
586 | } | 586 | } |
587 | EXPORT_SYMBOL_GPL(dma_buf_unmap_attachment); | 587 | EXPORT_SYMBOL_GPL(dma_buf_unmap_attachment); |
588 | 588 | ||
589 | static int __dma_buf_begin_cpu_access(struct dma_buf *dmabuf, | ||
590 | enum dma_data_direction direction) | ||
591 | { | ||
592 | bool write = (direction == DMA_BIDIRECTIONAL || | ||
593 | direction == DMA_TO_DEVICE); | ||
594 | struct reservation_object *resv = dmabuf->resv; | ||
595 | long ret; | ||
596 | |||
597 | /* Wait on any implicit rendering fences */ | ||
598 | ret = reservation_object_wait_timeout_rcu(resv, write, true, | ||
599 | MAX_SCHEDULE_TIMEOUT); | ||
600 | if (ret < 0) | ||
601 | return ret; | ||
602 | |||
603 | return 0; | ||
604 | } | ||
589 | 605 | ||
590 | /** | 606 | /** |
591 | * dma_buf_begin_cpu_access - Must be called before accessing a dma_buf from the | 607 | * dma_buf_begin_cpu_access - Must be called before accessing a dma_buf from the |
@@ -608,6 +624,13 @@ int dma_buf_begin_cpu_access(struct dma_buf *dmabuf, | |||
608 | if (dmabuf->ops->begin_cpu_access) | 624 | if (dmabuf->ops->begin_cpu_access) |
609 | ret = dmabuf->ops->begin_cpu_access(dmabuf, direction); | 625 | ret = dmabuf->ops->begin_cpu_access(dmabuf, direction); |
610 | 626 | ||
627 | /* Ensure that all fences are waited upon - but we first allow | ||
628 | * the native handler the chance to do so more efficiently if it | ||
629 | * chooses. A double invocation here will be reasonably cheap no-op. | ||
630 | */ | ||
631 | if (ret == 0) | ||
632 | ret = __dma_buf_begin_cpu_access(dmabuf, direction); | ||
633 | |||
611 | return ret; | 634 | return ret; |
612 | } | 635 | } |
613 | EXPORT_SYMBOL_GPL(dma_buf_begin_cpu_access); | 636 | EXPORT_SYMBOL_GPL(dma_buf_begin_cpu_access); |
diff --git a/drivers/dma-buf/fence-array.c b/drivers/dma-buf/fence-array.c index ee500226197b..f1989fcaf354 100644 --- a/drivers/dma-buf/fence-array.c +++ b/drivers/dma-buf/fence-array.c | |||
@@ -107,14 +107,14 @@ EXPORT_SYMBOL(fence_array_ops); | |||
107 | * @fences: [in] array containing the fences | 107 | * @fences: [in] array containing the fences |
108 | * @context: [in] fence context to use | 108 | * @context: [in] fence context to use |
109 | * @seqno: [in] sequence number to use | 109 | * @seqno: [in] sequence number to use |
110 | * @signal_on_any [in] signal on any fence in the array | 110 | * @signal_on_any: [in] signal on any fence in the array |
111 | * | 111 | * |
112 | * Allocate a fence_array object and initialize the base fence with fence_init(). | 112 | * Allocate a fence_array object and initialize the base fence with fence_init(). |
113 | * In case of error it returns NULL. | 113 | * In case of error it returns NULL. |
114 | * | 114 | * |
115 | * The caller should allocte the fences array with num_fences size | 115 | * The caller should allocate the fences array with num_fences size |
116 | * and fill it with the fences it wants to add to the object. Ownership of this | 116 | * and fill it with the fences it wants to add to the object. Ownership of this |
117 | * array is take and fence_put() is used on each fence on release. | 117 | * array is taken and fence_put() is used on each fence on release. |
118 | * | 118 | * |
119 | * If @signal_on_any is true the fence array signals if any fence in the array | 119 | * If @signal_on_any is true the fence array signals if any fence in the array |
120 | * signals, otherwise it signals when all fences in the array signal. | 120 | * signals, otherwise it signals when all fences in the array signal. |
diff --git a/drivers/dma-buf/reservation.c b/drivers/dma-buf/reservation.c index 9566a62ad8e3..723d8af988e5 100644 --- a/drivers/dma-buf/reservation.c +++ b/drivers/dma-buf/reservation.c | |||
@@ -205,7 +205,7 @@ done: | |||
205 | * @fence: the shared fence to add | 205 | * @fence: the shared fence to add |
206 | * | 206 | * |
207 | * Add a fence to a shared slot, obj->lock must be held, and | 207 | * Add a fence to a shared slot, obj->lock must be held, and |
208 | * reservation_object_reserve_shared_fence has been called. | 208 | * reservation_object_reserve_shared() has been called. |
209 | */ | 209 | */ |
210 | void reservation_object_add_shared_fence(struct reservation_object *obj, | 210 | void reservation_object_add_shared_fence(struct reservation_object *obj, |
211 | struct fence *fence) | 211 | struct fence *fence) |
diff --git a/drivers/gpu/drm/Makefile b/drivers/gpu/drm/Makefile index 0238bf8bc8c3..193ff2d09479 100644 --- a/drivers/gpu/drm/Makefile +++ b/drivers/gpu/drm/Makefile | |||
@@ -12,7 +12,8 @@ drm-y := drm_auth.o drm_bufs.o drm_cache.o \ | |||
12 | drm_info.o drm_debugfs.o drm_encoder_slave.o \ | 12 | drm_info.o drm_debugfs.o drm_encoder_slave.o \ |
13 | drm_trace_points.o drm_global.o drm_prime.o \ | 13 | drm_trace_points.o drm_global.o drm_prime.o \ |
14 | drm_rect.o drm_vma_manager.o drm_flip_work.o \ | 14 | drm_rect.o drm_vma_manager.o drm_flip_work.o \ |
15 | drm_modeset_lock.o drm_atomic.o drm_bridge.o | 15 | drm_modeset_lock.o drm_atomic.o drm_bridge.o \ |
16 | drm_framebuffer.o drm_connector.o drm_blend.o | ||
16 | 17 | ||
17 | drm-$(CONFIG_COMPAT) += drm_ioc32.o | 18 | drm-$(CONFIG_COMPAT) += drm_ioc32.o |
18 | drm-$(CONFIG_DRM_GEM_CMA_HELPER) += drm_gem_cma_helper.o | 19 | drm-$(CONFIG_DRM_GEM_CMA_HELPER) += drm_gem_cma_helper.o |
@@ -24,7 +25,7 @@ drm-$(CONFIG_AGP) += drm_agpsupport.o | |||
24 | 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 \ |
25 | drm_plane_helper.o drm_dp_mst_topology.o drm_atomic_helper.o \ | 26 | drm_plane_helper.o drm_dp_mst_topology.o drm_atomic_helper.o \ |
26 | drm_kms_helper_common.o drm_dp_dual_mode_helper.o \ | 27 | drm_kms_helper_common.o drm_dp_dual_mode_helper.o \ |
27 | drm_simple_kms_helper.o drm_blend.o | 28 | drm_simple_kms_helper.o drm_modeset_helper.o |
28 | 29 | ||
29 | drm_kms_helper-$(CONFIG_DRM_LOAD_EDID_FIRMWARE) += drm_edid_load.o | 30 | drm_kms_helper-$(CONFIG_DRM_LOAD_EDID_FIRMWARE) += drm_edid_load.o |
30 | drm_kms_helper-$(CONFIG_DRM_FBDEV_EMULATION) += drm_fb_helper.o | 31 | drm_kms_helper-$(CONFIG_DRM_FBDEV_EMULATION) += drm_fb_helper.o |
diff --git a/drivers/gpu/drm/amd/amdgpu/dce_v10_0.c b/drivers/gpu/drm/amd/amdgpu/dce_v10_0.c index c1b04e9aab57..741da36cd8b6 100644 --- a/drivers/gpu/drm/amd/amdgpu/dce_v10_0.c +++ b/drivers/gpu/drm/amd/amdgpu/dce_v10_0.c | |||
@@ -2071,6 +2071,7 @@ static int dce_v10_0_crtc_do_set_base(struct drm_crtc *crtc, | |||
2071 | u32 tmp, viewport_w, viewport_h; | 2071 | u32 tmp, viewport_w, viewport_h; |
2072 | int r; | 2072 | int r; |
2073 | bool bypass_lut = false; | 2073 | bool bypass_lut = false; |
2074 | char *format_name; | ||
2074 | 2075 | ||
2075 | /* no fb bound */ | 2076 | /* no fb bound */ |
2076 | if (!atomic && !crtc->primary->fb) { | 2077 | if (!atomic && !crtc->primary->fb) { |
@@ -2182,8 +2183,9 @@ static int dce_v10_0_crtc_do_set_base(struct drm_crtc *crtc, | |||
2182 | bypass_lut = true; | 2183 | bypass_lut = true; |
2183 | break; | 2184 | break; |
2184 | default: | 2185 | default: |
2185 | DRM_ERROR("Unsupported screen format %s\n", | 2186 | format_name = drm_get_format_name(target_fb->pixel_format); |
2186 | drm_get_format_name(target_fb->pixel_format)); | 2187 | DRM_ERROR("Unsupported screen format %s\n", format_name); |
2188 | kfree(format_name); | ||
2187 | return -EINVAL; | 2189 | return -EINVAL; |
2188 | } | 2190 | } |
2189 | 2191 | ||
diff --git a/drivers/gpu/drm/amd/amdgpu/dce_v11_0.c b/drivers/gpu/drm/amd/amdgpu/dce_v11_0.c index d4bf133908b1..2282eb60aba6 100644 --- a/drivers/gpu/drm/amd/amdgpu/dce_v11_0.c +++ b/drivers/gpu/drm/amd/amdgpu/dce_v11_0.c | |||
@@ -2046,6 +2046,7 @@ static int dce_v11_0_crtc_do_set_base(struct drm_crtc *crtc, | |||
2046 | u32 tmp, viewport_w, viewport_h; | 2046 | u32 tmp, viewport_w, viewport_h; |
2047 | int r; | 2047 | int r; |
2048 | bool bypass_lut = false; | 2048 | bool bypass_lut = false; |
2049 | char *format_name; | ||
2049 | 2050 | ||
2050 | /* no fb bound */ | 2051 | /* no fb bound */ |
2051 | if (!atomic && !crtc->primary->fb) { | 2052 | if (!atomic && !crtc->primary->fb) { |
@@ -2157,8 +2158,9 @@ static int dce_v11_0_crtc_do_set_base(struct drm_crtc *crtc, | |||
2157 | bypass_lut = true; | 2158 | bypass_lut = true; |
2158 | break; | 2159 | break; |
2159 | default: | 2160 | default: |
2160 | DRM_ERROR("Unsupported screen format %s\n", | 2161 | format_name = drm_get_format_name(target_fb->pixel_format); |
2161 | drm_get_format_name(target_fb->pixel_format)); | 2162 | DRM_ERROR("Unsupported screen format %s\n", format_name); |
2163 | kfree(format_name); | ||
2162 | return -EINVAL; | 2164 | return -EINVAL; |
2163 | } | 2165 | } |
2164 | 2166 | ||
diff --git a/drivers/gpu/drm/amd/amdgpu/dce_v8_0.c b/drivers/gpu/drm/amd/amdgpu/dce_v8_0.c index 4fdfab1e9200..8b7ad345771f 100644 --- a/drivers/gpu/drm/amd/amdgpu/dce_v8_0.c +++ b/drivers/gpu/drm/amd/amdgpu/dce_v8_0.c | |||
@@ -1952,6 +1952,7 @@ static int dce_v8_0_crtc_do_set_base(struct drm_crtc *crtc, | |||
1952 | u32 viewport_w, viewport_h; | 1952 | u32 viewport_w, viewport_h; |
1953 | int r; | 1953 | int r; |
1954 | bool bypass_lut = false; | 1954 | bool bypass_lut = false; |
1955 | char *format_name; | ||
1955 | 1956 | ||
1956 | /* no fb bound */ | 1957 | /* no fb bound */ |
1957 | if (!atomic && !crtc->primary->fb) { | 1958 | if (!atomic && !crtc->primary->fb) { |
@@ -2056,8 +2057,9 @@ static int dce_v8_0_crtc_do_set_base(struct drm_crtc *crtc, | |||
2056 | bypass_lut = true; | 2057 | bypass_lut = true; |
2057 | break; | 2058 | break; |
2058 | default: | 2059 | default: |
2059 | DRM_ERROR("Unsupported screen format %s\n", | 2060 | format_name = drm_get_format_name(target_fb->pixel_format); |
2060 | drm_get_format_name(target_fb->pixel_format)); | 2061 | DRM_ERROR("Unsupported screen format %s\n", format_name); |
2062 | kfree(format_name); | ||
2061 | return -EINVAL; | 2063 | return -EINVAL; |
2062 | } | 2064 | } |
2063 | 2065 | ||
diff --git a/drivers/gpu/drm/arc/arcpgu_crtc.c b/drivers/gpu/drm/arc/arcpgu_crtc.c index ee0a61c2861b..7130b044b004 100644 --- a/drivers/gpu/drm/arc/arcpgu_crtc.c +++ b/drivers/gpu/drm/arc/arcpgu_crtc.c | |||
@@ -183,8 +183,6 @@ static void arc_pgu_plane_atomic_update(struct drm_plane *plane, | |||
183 | } | 183 | } |
184 | 184 | ||
185 | static const struct drm_plane_helper_funcs arc_pgu_plane_helper_funcs = { | 185 | static const struct drm_plane_helper_funcs arc_pgu_plane_helper_funcs = { |
186 | .prepare_fb = NULL, | ||
187 | .cleanup_fb = NULL, | ||
188 | .atomic_update = arc_pgu_plane_atomic_update, | 186 | .atomic_update = arc_pgu_plane_atomic_update, |
189 | }; | 187 | }; |
190 | 188 | ||
diff --git a/drivers/gpu/drm/armada/armada_drv.c b/drivers/gpu/drm/armada/armada_drv.c index f5ebdd681445..1e0e68f608e4 100644 --- a/drivers/gpu/drm/armada/armada_drv.c +++ b/drivers/gpu/drm/armada/armada_drv.c | |||
@@ -211,7 +211,7 @@ static struct drm_driver armada_drm_driver = { | |||
211 | .desc = "Armada SoC DRM", | 211 | .desc = "Armada SoC DRM", |
212 | .date = "20120730", | 212 | .date = "20120730", |
213 | .driver_features = DRIVER_GEM | DRIVER_MODESET | | 213 | .driver_features = DRIVER_GEM | DRIVER_MODESET | |
214 | DRIVER_HAVE_IRQ | DRIVER_PRIME, | 214 | DRIVER_PRIME, |
215 | .ioctls = armada_ioctls, | 215 | .ioctls = armada_ioctls, |
216 | .fops = &armada_drm_fops, | 216 | .fops = &armada_drm_fops, |
217 | }; | 217 | }; |
diff --git a/drivers/gpu/drm/atmel-hlcdc/atmel_hlcdc_plane.c b/drivers/gpu/drm/atmel-hlcdc/atmel_hlcdc_plane.c index 146809a97a07..72e6b7dd457b 100644 --- a/drivers/gpu/drm/atmel-hlcdc/atmel_hlcdc_plane.c +++ b/drivers/gpu/drm/atmel-hlcdc/atmel_hlcdc_plane.c | |||
@@ -755,7 +755,7 @@ static int atmel_hlcdc_plane_atomic_check(struct drm_plane *p, | |||
755 | } | 755 | } |
756 | 756 | ||
757 | static int atmel_hlcdc_plane_prepare_fb(struct drm_plane *p, | 757 | static int atmel_hlcdc_plane_prepare_fb(struct drm_plane *p, |
758 | const struct drm_plane_state *new_state) | 758 | struct drm_plane_state *new_state) |
759 | { | 759 | { |
760 | /* | 760 | /* |
761 | * FIXME: we should avoid this const -> non-const cast but it's | 761 | * FIXME: we should avoid this const -> non-const cast but it's |
@@ -780,7 +780,7 @@ static int atmel_hlcdc_plane_prepare_fb(struct drm_plane *p, | |||
780 | } | 780 | } |
781 | 781 | ||
782 | static void atmel_hlcdc_plane_cleanup_fb(struct drm_plane *p, | 782 | static void atmel_hlcdc_plane_cleanup_fb(struct drm_plane *p, |
783 | const struct drm_plane_state *old_state) | 783 | struct drm_plane_state *old_state) |
784 | { | 784 | { |
785 | /* | 785 | /* |
786 | * FIXME: we should avoid this const -> non-const cast but it's | 786 | * FIXME: we should avoid this const -> non-const cast but it's |
diff --git a/drivers/gpu/drm/bridge/dw-hdmi-ahb-audio.c b/drivers/gpu/drm/bridge/dw-hdmi-ahb-audio.c index 122bb015f4a9..8f2d1379c880 100644 --- a/drivers/gpu/drm/bridge/dw-hdmi-ahb-audio.c +++ b/drivers/gpu/drm/bridge/dw-hdmi-ahb-audio.c | |||
@@ -640,7 +640,6 @@ static struct platform_driver snd_dw_hdmi_driver = { | |||
640 | .remove = snd_dw_hdmi_remove, | 640 | .remove = snd_dw_hdmi_remove, |
641 | .driver = { | 641 | .driver = { |
642 | .name = DRIVER_NAME, | 642 | .name = DRIVER_NAME, |
643 | .owner = THIS_MODULE, | ||
644 | .pm = PM_OPS, | 643 | .pm = PM_OPS, |
645 | }, | 644 | }, |
646 | }; | 645 | }; |
diff --git a/drivers/gpu/drm/drm_atomic.c b/drivers/gpu/drm/drm_atomic.c index fa3930757972..5cb2e22d5d55 100644 --- a/drivers/gpu/drm/drm_atomic.c +++ b/drivers/gpu/drm/drm_atomic.c | |||
@@ -837,8 +837,9 @@ static int drm_atomic_plane_check(struct drm_plane *plane, | |||
837 | /* Check whether this plane supports the fb pixel format. */ | 837 | /* Check whether this plane supports the fb pixel format. */ |
838 | ret = drm_plane_check_pixel_format(plane, state->fb->pixel_format); | 838 | ret = drm_plane_check_pixel_format(plane, state->fb->pixel_format); |
839 | if (ret) { | 839 | if (ret) { |
840 | DRM_DEBUG_ATOMIC("Invalid pixel format %s\n", | 840 | char *format_name = drm_get_format_name(state->fb->pixel_format); |
841 | drm_get_format_name(state->fb->pixel_format)); | 841 | DRM_DEBUG_ATOMIC("Invalid pixel format %s\n", format_name); |
842 | kfree(format_name); | ||
842 | return ret; | 843 | return ret; |
843 | } | 844 | } |
844 | 845 | ||
diff --git a/drivers/gpu/drm/drm_atomic_helper.c b/drivers/gpu/drm/drm_atomic_helper.c index e1f5de274913..9abe0a242f96 100644 --- a/drivers/gpu/drm/drm_atomic_helper.c +++ b/drivers/gpu/drm/drm_atomic_helper.c | |||
@@ -594,7 +594,7 @@ drm_atomic_helper_check_planes(struct drm_device *dev, | |||
594 | struct drm_plane_state *plane_state; | 594 | struct drm_plane_state *plane_state; |
595 | int i, ret = 0; | 595 | int i, ret = 0; |
596 | 596 | ||
597 | ret = drm_atomic_helper_normalize_zpos(dev, state); | 597 | ret = drm_atomic_normalize_zpos(dev, state); |
598 | if (ret) | 598 | if (ret) |
599 | return ret; | 599 | return ret; |
600 | 600 | ||
diff --git a/drivers/gpu/drm/drm_blend.c b/drivers/gpu/drm/drm_blend.c index f3c0942bd756..0813b7e021be 100644 --- a/drivers/gpu/drm/drm_blend.c +++ b/drivers/gpu/drm/drm_blend.c | |||
@@ -193,8 +193,7 @@ done: | |||
193 | } | 193 | } |
194 | 194 | ||
195 | /** | 195 | /** |
196 | * drm_atomic_helper_normalize_zpos - calculate normalized zpos values for all | 196 | * drm_atomic_normalize_zpos - calculate normalized zpos values for all crtcs |
197 | * crtcs | ||
198 | * @dev: DRM device | 197 | * @dev: DRM device |
199 | * @state: atomic state of DRM device | 198 | * @state: atomic state of DRM device |
200 | * | 199 | * |
@@ -205,8 +204,8 @@ done: | |||
205 | * RETURNS | 204 | * RETURNS |
206 | * Zero for success or -errno | 205 | * Zero for success or -errno |
207 | */ | 206 | */ |
208 | int drm_atomic_helper_normalize_zpos(struct drm_device *dev, | 207 | int drm_atomic_normalize_zpos(struct drm_device *dev, |
209 | struct drm_atomic_state *state) | 208 | struct drm_atomic_state *state) |
210 | { | 209 | { |
211 | struct drm_crtc *crtc; | 210 | struct drm_crtc *crtc; |
212 | struct drm_crtc_state *crtc_state; | 211 | struct drm_crtc_state *crtc_state; |
@@ -236,3 +235,4 @@ int drm_atomic_helper_normalize_zpos(struct drm_device *dev, | |||
236 | } | 235 | } |
237 | return 0; | 236 | return 0; |
238 | } | 237 | } |
238 | EXPORT_SYMBOL(drm_atomic_normalize_zpos); | ||
diff --git a/drivers/gpu/drm/drm_connector.c b/drivers/gpu/drm/drm_connector.c new file mode 100644 index 000000000000..26bb78c76481 --- /dev/null +++ b/drivers/gpu/drm/drm_connector.c | |||
@@ -0,0 +1,1123 @@ | |||
1 | /* | ||
2 | * Copyright (c) 2016 Intel Corporation | ||
3 | * | ||
4 | * Permission to use, copy, modify, distribute, and sell this software and its | ||
5 | * documentation for any purpose is hereby granted without fee, provided that | ||
6 | * the above copyright notice appear in all copies and that both that copyright | ||
7 | * notice and this permission notice appear in supporting documentation, and | ||
8 | * that the name of the copyright holders not be used in advertising or | ||
9 | * publicity pertaining to distribution of the software without specific, | ||
10 | * written prior permission. The copyright holders make no representations | ||
11 | * about the suitability of this software for any purpose. It is provided "as | ||
12 | * is" without express or implied warranty. | ||
13 | * | ||
14 | * THE COPYRIGHT HOLDERS DISCLAIM ALL WARRANTIES WITH REGARD TO THIS SOFTWARE, | ||
15 | * INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS, IN NO | ||
16 | * EVENT SHALL THE COPYRIGHT HOLDERS BE LIABLE FOR ANY SPECIAL, INDIRECT OR | ||
17 | * CONSEQUENTIAL DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM LOSS OF USE, | ||
18 | * DATA OR PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER | ||
19 | * TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR PERFORMANCE | ||
20 | * OF THIS SOFTWARE. | ||
21 | */ | ||
22 | |||
23 | #include <drm/drmP.h> | ||
24 | #include <drm/drm_connector.h> | ||
25 | #include <drm/drm_edid.h> | ||
26 | |||
27 | #include "drm_crtc_internal.h" | ||
28 | #include "drm_internal.h" | ||
29 | |||
30 | /** | ||
31 | * DOC: overview | ||
32 | * | ||
33 | * In DRM connectors are the general abstraction for display sinks, and include | ||
34 | * als fixed panels or anything else that can display pixels in some form. As | ||
35 | * opposed to all other KMS objects representing hardware (like CRTC, encoder or | ||
36 | * plane abstractions) connectors can be hotplugged and unplugged at runtime. | ||
37 | * Hence they are reference-counted using drm_connector_reference() and | ||
38 | * drm_connector_unreference(). | ||
39 | * | ||
40 | * KMS driver must create, initialize, register and attach at a struct | ||
41 | * &drm_connector for each such sink. The instance is created as other KMS | ||
42 | * objects and initialized by setting the following fields. | ||
43 | * | ||
44 | * The connector is then registered with a call to drm_connector_init() with a | ||
45 | * pointer to the connector functions and a connector type, and exposed through | ||
46 | * sysfs with a call to drm_connector_register(). | ||
47 | * | ||
48 | * Connectors must be attached to an encoder to be used. For devices that map | ||
49 | * connectors to encoders 1:1, the connector should be attached at | ||
50 | * initialization time with a call to drm_mode_connector_attach_encoder(). The | ||
51 | * driver must also set the struct &drm_connector encoder field to point to the | ||
52 | * attached encoder. | ||
53 | * | ||
54 | * For connectors which are not fixed (like built-in panels) the driver needs to | ||
55 | * support hotplug notifications. The simplest way to do that is by using the | ||
56 | * probe helpers, see drm_kms_helper_poll_init() for connectors which don't have | ||
57 | * hardware support for hotplug interrupts. Connectors with hardware hotplug | ||
58 | * support can instead use e.g. drm_helper_hpd_irq_event(). | ||
59 | */ | ||
60 | |||
61 | struct drm_conn_prop_enum_list { | ||
62 | int type; | ||
63 | const char *name; | ||
64 | struct ida ida; | ||
65 | }; | ||
66 | |||
67 | /* | ||
68 | * Connector and encoder types. | ||
69 | */ | ||
70 | static struct drm_conn_prop_enum_list drm_connector_enum_list[] = { | ||
71 | { DRM_MODE_CONNECTOR_Unknown, "Unknown" }, | ||
72 | { DRM_MODE_CONNECTOR_VGA, "VGA" }, | ||
73 | { DRM_MODE_CONNECTOR_DVII, "DVI-I" }, | ||
74 | { DRM_MODE_CONNECTOR_DVID, "DVI-D" }, | ||
75 | { DRM_MODE_CONNECTOR_DVIA, "DVI-A" }, | ||
76 | { DRM_MODE_CONNECTOR_Composite, "Composite" }, | ||
77 | { DRM_MODE_CONNECTOR_SVIDEO, "SVIDEO" }, | ||
78 | { DRM_MODE_CONNECTOR_LVDS, "LVDS" }, | ||
79 | { DRM_MODE_CONNECTOR_Component, "Component" }, | ||
80 | { DRM_MODE_CONNECTOR_9PinDIN, "DIN" }, | ||
81 | { DRM_MODE_CONNECTOR_DisplayPort, "DP" }, | ||
82 | { DRM_MODE_CONNECTOR_HDMIA, "HDMI-A" }, | ||
83 | { DRM_MODE_CONNECTOR_HDMIB, "HDMI-B" }, | ||
84 | { DRM_MODE_CONNECTOR_TV, "TV" }, | ||
85 | { DRM_MODE_CONNECTOR_eDP, "eDP" }, | ||
86 | { DRM_MODE_CONNECTOR_VIRTUAL, "Virtual" }, | ||
87 | { DRM_MODE_CONNECTOR_DSI, "DSI" }, | ||
88 | { DRM_MODE_CONNECTOR_DPI, "DPI" }, | ||
89 | }; | ||
90 | |||
91 | void drm_connector_ida_init(void) | ||
92 | { | ||
93 | int i; | ||
94 | |||
95 | for (i = 0; i < ARRAY_SIZE(drm_connector_enum_list); i++) | ||
96 | ida_init(&drm_connector_enum_list[i].ida); | ||
97 | } | ||
98 | |||
99 | void drm_connector_ida_destroy(void) | ||
100 | { | ||
101 | int i; | ||
102 | |||
103 | for (i = 0; i < ARRAY_SIZE(drm_connector_enum_list); i++) | ||
104 | ida_destroy(&drm_connector_enum_list[i].ida); | ||
105 | } | ||
106 | |||
107 | /** | ||
108 | * drm_connector_get_cmdline_mode - reads the user's cmdline mode | ||
109 | * @connector: connector to quwery | ||
110 | * | ||
111 | * The kernel supports per-connector configuration of its consoles through | ||
112 | * use of the video= parameter. This function parses that option and | ||
113 | * extracts the user's specified mode (or enable/disable status) for a | ||
114 | * particular connector. This is typically only used during the early fbdev | ||
115 | * setup. | ||
116 | */ | ||
117 | static void drm_connector_get_cmdline_mode(struct drm_connector *connector) | ||
118 | { | ||
119 | struct drm_cmdline_mode *mode = &connector->cmdline_mode; | ||
120 | char *option = NULL; | ||
121 | |||
122 | if (fb_get_options(connector->name, &option)) | ||
123 | return; | ||
124 | |||
125 | if (!drm_mode_parse_command_line_for_connector(option, | ||
126 | connector, | ||
127 | mode)) | ||
128 | return; | ||
129 | |||
130 | if (mode->force) { | ||
131 | const char *s; | ||
132 | |||
133 | switch (mode->force) { | ||
134 | case DRM_FORCE_OFF: | ||
135 | s = "OFF"; | ||
136 | break; | ||
137 | case DRM_FORCE_ON_DIGITAL: | ||
138 | s = "ON - dig"; | ||
139 | break; | ||
140 | default: | ||
141 | case DRM_FORCE_ON: | ||
142 | s = "ON"; | ||
143 | break; | ||
144 | } | ||
145 | |||
146 | DRM_INFO("forcing %s connector %s\n", connector->name, s); | ||
147 | connector->force = mode->force; | ||
148 | } | ||
149 | |||
150 | DRM_DEBUG_KMS("cmdline mode for connector %s %dx%d@%dHz%s%s%s\n", | ||
151 | connector->name, | ||
152 | mode->xres, mode->yres, | ||
153 | mode->refresh_specified ? mode->refresh : 60, | ||
154 | mode->rb ? " reduced blanking" : "", | ||
155 | mode->margins ? " with margins" : "", | ||
156 | mode->interlace ? " interlaced" : ""); | ||
157 | } | ||
158 | |||
159 | static void drm_connector_free(struct kref *kref) | ||
160 | { | ||
161 | struct drm_connector *connector = | ||
162 | container_of(kref, struct drm_connector, base.refcount); | ||
163 | struct drm_device *dev = connector->dev; | ||
164 | |||
165 | drm_mode_object_unregister(dev, &connector->base); | ||
166 | connector->funcs->destroy(connector); | ||
167 | } | ||
168 | |||
169 | /** | ||
170 | * drm_connector_init - Init a preallocated connector | ||
171 | * @dev: DRM device | ||
172 | * @connector: the connector to init | ||
173 | * @funcs: callbacks for this connector | ||
174 | * @connector_type: user visible type of the connector | ||
175 | * | ||
176 | * Initialises a preallocated connector. Connectors should be | ||
177 | * subclassed as part of driver connector objects. | ||
178 | * | ||
179 | * Returns: | ||
180 | * Zero on success, error code on failure. | ||
181 | */ | ||
182 | int drm_connector_init(struct drm_device *dev, | ||
183 | struct drm_connector *connector, | ||
184 | const struct drm_connector_funcs *funcs, | ||
185 | int connector_type) | ||
186 | { | ||
187 | struct drm_mode_config *config = &dev->mode_config; | ||
188 | int ret; | ||
189 | struct ida *connector_ida = | ||
190 | &drm_connector_enum_list[connector_type].ida; | ||
191 | |||
192 | drm_modeset_lock_all(dev); | ||
193 | |||
194 | ret = drm_mode_object_get_reg(dev, &connector->base, | ||
195 | DRM_MODE_OBJECT_CONNECTOR, | ||
196 | false, drm_connector_free); | ||
197 | if (ret) | ||
198 | goto out_unlock; | ||
199 | |||
200 | connector->base.properties = &connector->properties; | ||
201 | connector->dev = dev; | ||
202 | connector->funcs = funcs; | ||
203 | |||
204 | ret = ida_simple_get(&config->connector_ida, 0, 0, GFP_KERNEL); | ||
205 | if (ret < 0) | ||
206 | goto out_put; | ||
207 | connector->index = ret; | ||
208 | ret = 0; | ||
209 | |||
210 | connector->connector_type = connector_type; | ||
211 | connector->connector_type_id = | ||
212 | ida_simple_get(connector_ida, 1, 0, GFP_KERNEL); | ||
213 | if (connector->connector_type_id < 0) { | ||
214 | ret = connector->connector_type_id; | ||
215 | goto out_put_id; | ||
216 | } | ||
217 | connector->name = | ||
218 | kasprintf(GFP_KERNEL, "%s-%d", | ||
219 | drm_connector_enum_list[connector_type].name, | ||
220 | connector->connector_type_id); | ||
221 | if (!connector->name) { | ||
222 | ret = -ENOMEM; | ||
223 | goto out_put_type_id; | ||
224 | } | ||
225 | |||
226 | INIT_LIST_HEAD(&connector->probed_modes); | ||
227 | INIT_LIST_HEAD(&connector->modes); | ||
228 | connector->edid_blob_ptr = NULL; | ||
229 | connector->status = connector_status_unknown; | ||
230 | |||
231 | drm_connector_get_cmdline_mode(connector); | ||
232 | |||
233 | /* We should add connectors at the end to avoid upsetting the connector | ||
234 | * index too much. */ | ||
235 | list_add_tail(&connector->head, &config->connector_list); | ||
236 | config->num_connector++; | ||
237 | |||
238 | if (connector_type != DRM_MODE_CONNECTOR_VIRTUAL) | ||
239 | drm_object_attach_property(&connector->base, | ||
240 | config->edid_property, | ||
241 | 0); | ||
242 | |||
243 | drm_object_attach_property(&connector->base, | ||
244 | config->dpms_property, 0); | ||
245 | |||
246 | if (drm_core_check_feature(dev, DRIVER_ATOMIC)) { | ||
247 | drm_object_attach_property(&connector->base, config->prop_crtc_id, 0); | ||
248 | } | ||
249 | |||
250 | connector->debugfs_entry = NULL; | ||
251 | out_put_type_id: | ||
252 | if (ret) | ||
253 | ida_remove(connector_ida, connector->connector_type_id); | ||
254 | out_put_id: | ||
255 | if (ret) | ||
256 | ida_remove(&config->connector_ida, connector->index); | ||
257 | out_put: | ||
258 | if (ret) | ||
259 | drm_mode_object_unregister(dev, &connector->base); | ||
260 | |||
261 | out_unlock: | ||
262 | drm_modeset_unlock_all(dev); | ||
263 | |||
264 | return ret; | ||
265 | } | ||
266 | EXPORT_SYMBOL(drm_connector_init); | ||
267 | |||
268 | /** | ||
269 | * drm_mode_connector_attach_encoder - attach a connector to an encoder | ||
270 | * @connector: connector to attach | ||
271 | * @encoder: encoder to attach @connector to | ||
272 | * | ||
273 | * This function links up a connector to an encoder. Note that the routing | ||
274 | * restrictions between encoders and crtcs are exposed to userspace through the | ||
275 | * possible_clones and possible_crtcs bitmasks. | ||
276 | * | ||
277 | * Returns: | ||
278 | * Zero on success, negative errno on failure. | ||
279 | */ | ||
280 | int drm_mode_connector_attach_encoder(struct drm_connector *connector, | ||
281 | struct drm_encoder *encoder) | ||
282 | { | ||
283 | int i; | ||
284 | |||
285 | /* | ||
286 | * In the past, drivers have attempted to model the static association | ||
287 | * of connector to encoder in simple connector/encoder devices using a | ||
288 | * direct assignment of connector->encoder = encoder. This connection | ||
289 | * is a logical one and the responsibility of the core, so drivers are | ||
290 | * expected not to mess with this. | ||
291 | * | ||
292 | * Note that the error return should've been enough here, but a large | ||
293 | * majority of drivers ignores the return value, so add in a big WARN | ||
294 | * to get people's attention. | ||
295 | */ | ||
296 | if (WARN_ON(connector->encoder)) | ||
297 | return -EINVAL; | ||
298 | |||
299 | for (i = 0; i < DRM_CONNECTOR_MAX_ENCODER; i++) { | ||
300 | if (connector->encoder_ids[i] == 0) { | ||
301 | connector->encoder_ids[i] = encoder->base.id; | ||
302 | return 0; | ||
303 | } | ||
304 | } | ||
305 | return -ENOMEM; | ||
306 | } | ||
307 | EXPORT_SYMBOL(drm_mode_connector_attach_encoder); | ||
308 | |||
309 | static void drm_mode_remove(struct drm_connector *connector, | ||
310 | struct drm_display_mode *mode) | ||
311 | { | ||
312 | list_del(&mode->head); | ||
313 | drm_mode_destroy(connector->dev, mode); | ||
314 | } | ||
315 | |||
316 | /** | ||
317 | * drm_connector_cleanup - cleans up an initialised connector | ||
318 | * @connector: connector to cleanup | ||
319 | * | ||
320 | * Cleans up the connector but doesn't free the object. | ||
321 | */ | ||
322 | void drm_connector_cleanup(struct drm_connector *connector) | ||
323 | { | ||
324 | struct drm_device *dev = connector->dev; | ||
325 | struct drm_display_mode *mode, *t; | ||
326 | |||
327 | /* The connector should have been removed from userspace long before | ||
328 | * it is finally destroyed. | ||
329 | */ | ||
330 | if (WARN_ON(connector->registered)) | ||
331 | drm_connector_unregister(connector); | ||
332 | |||
333 | if (connector->tile_group) { | ||
334 | drm_mode_put_tile_group(dev, connector->tile_group); | ||
335 | connector->tile_group = NULL; | ||
336 | } | ||
337 | |||
338 | list_for_each_entry_safe(mode, t, &connector->probed_modes, head) | ||
339 | drm_mode_remove(connector, mode); | ||
340 | |||
341 | list_for_each_entry_safe(mode, t, &connector->modes, head) | ||
342 | drm_mode_remove(connector, mode); | ||
343 | |||
344 | ida_remove(&drm_connector_enum_list[connector->connector_type].ida, | ||
345 | connector->connector_type_id); | ||
346 | |||
347 | ida_remove(&dev->mode_config.connector_ida, | ||
348 | connector->index); | ||
349 | |||
350 | kfree(connector->display_info.bus_formats); | ||
351 | drm_mode_object_unregister(dev, &connector->base); | ||
352 | kfree(connector->name); | ||
353 | connector->name = NULL; | ||
354 | list_del(&connector->head); | ||
355 | dev->mode_config.num_connector--; | ||
356 | |||
357 | WARN_ON(connector->state && !connector->funcs->atomic_destroy_state); | ||
358 | if (connector->state && connector->funcs->atomic_destroy_state) | ||
359 | connector->funcs->atomic_destroy_state(connector, | ||
360 | connector->state); | ||
361 | |||
362 | memset(connector, 0, sizeof(*connector)); | ||
363 | } | ||
364 | EXPORT_SYMBOL(drm_connector_cleanup); | ||
365 | |||
366 | /** | ||
367 | * drm_connector_register - register a connector | ||
368 | * @connector: the connector to register | ||
369 | * | ||
370 | * Register userspace interfaces for a connector | ||
371 | * | ||
372 | * Returns: | ||
373 | * Zero on success, error code on failure. | ||
374 | */ | ||
375 | int drm_connector_register(struct drm_connector *connector) | ||
376 | { | ||
377 | int ret; | ||
378 | |||
379 | if (connector->registered) | ||
380 | return 0; | ||
381 | |||
382 | ret = drm_sysfs_connector_add(connector); | ||
383 | if (ret) | ||
384 | return ret; | ||
385 | |||
386 | ret = drm_debugfs_connector_add(connector); | ||
387 | if (ret) { | ||
388 | goto err_sysfs; | ||
389 | } | ||
390 | |||
391 | if (connector->funcs->late_register) { | ||
392 | ret = connector->funcs->late_register(connector); | ||
393 | if (ret) | ||
394 | goto err_debugfs; | ||
395 | } | ||
396 | |||
397 | drm_mode_object_register(connector->dev, &connector->base); | ||
398 | |||
399 | connector->registered = true; | ||
400 | return 0; | ||
401 | |||
402 | err_debugfs: | ||
403 | drm_debugfs_connector_remove(connector); | ||
404 | err_sysfs: | ||
405 | drm_sysfs_connector_remove(connector); | ||
406 | return ret; | ||
407 | } | ||
408 | EXPORT_SYMBOL(drm_connector_register); | ||
409 | |||
410 | /** | ||
411 | * drm_connector_unregister - unregister a connector | ||
412 | * @connector: the connector to unregister | ||
413 | * | ||
414 | * Unregister userspace interfaces for a connector | ||
415 | */ | ||
416 | void drm_connector_unregister(struct drm_connector *connector) | ||
417 | { | ||
418 | if (!connector->registered) | ||
419 | return; | ||
420 | |||
421 | if (connector->funcs->early_unregister) | ||
422 | connector->funcs->early_unregister(connector); | ||
423 | |||
424 | drm_sysfs_connector_remove(connector); | ||
425 | drm_debugfs_connector_remove(connector); | ||
426 | |||
427 | connector->registered = false; | ||
428 | } | ||
429 | EXPORT_SYMBOL(drm_connector_unregister); | ||
430 | |||
431 | void drm_connector_unregister_all(struct drm_device *dev) | ||
432 | { | ||
433 | struct drm_connector *connector; | ||
434 | |||
435 | /* FIXME: taking the mode config mutex ends up in a clash with sysfs */ | ||
436 | list_for_each_entry(connector, &dev->mode_config.connector_list, head) | ||
437 | drm_connector_unregister(connector); | ||
438 | } | ||
439 | |||
440 | int drm_connector_register_all(struct drm_device *dev) | ||
441 | { | ||
442 | struct drm_connector *connector; | ||
443 | int ret; | ||
444 | |||
445 | /* FIXME: taking the mode config mutex ends up in a clash with | ||
446 | * fbcon/backlight registration */ | ||
447 | list_for_each_entry(connector, &dev->mode_config.connector_list, head) { | ||
448 | ret = drm_connector_register(connector); | ||
449 | if (ret) | ||
450 | goto err; | ||
451 | } | ||
452 | |||
453 | return 0; | ||
454 | |||
455 | err: | ||
456 | mutex_unlock(&dev->mode_config.mutex); | ||
457 | drm_connector_unregister_all(dev); | ||
458 | return ret; | ||
459 | } | ||
460 | |||
461 | /** | ||
462 | * drm_get_connector_status_name - return a string for connector status | ||
463 | * @status: connector status to compute name of | ||
464 | * | ||
465 | * In contrast to the other drm_get_*_name functions this one here returns a | ||
466 | * const pointer and hence is threadsafe. | ||
467 | */ | ||
468 | const char *drm_get_connector_status_name(enum drm_connector_status status) | ||
469 | { | ||
470 | if (status == connector_status_connected) | ||
471 | return "connected"; | ||
472 | else if (status == connector_status_disconnected) | ||
473 | return "disconnected"; | ||
474 | else | ||
475 | return "unknown"; | ||
476 | } | ||
477 | EXPORT_SYMBOL(drm_get_connector_status_name); | ||
478 | |||
479 | static const struct drm_prop_enum_list drm_subpixel_enum_list[] = { | ||
480 | { SubPixelUnknown, "Unknown" }, | ||
481 | { SubPixelHorizontalRGB, "Horizontal RGB" }, | ||
482 | { SubPixelHorizontalBGR, "Horizontal BGR" }, | ||
483 | { SubPixelVerticalRGB, "Vertical RGB" }, | ||
484 | { SubPixelVerticalBGR, "Vertical BGR" }, | ||
485 | { SubPixelNone, "None" }, | ||
486 | }; | ||
487 | |||
488 | /** | ||
489 | * drm_get_subpixel_order_name - return a string for a given subpixel enum | ||
490 | * @order: enum of subpixel_order | ||
491 | * | ||
492 | * Note you could abuse this and return something out of bounds, but that | ||
493 | * would be a caller error. No unscrubbed user data should make it here. | ||
494 | */ | ||
495 | const char *drm_get_subpixel_order_name(enum subpixel_order order) | ||
496 | { | ||
497 | return drm_subpixel_enum_list[order].name; | ||
498 | } | ||
499 | EXPORT_SYMBOL(drm_get_subpixel_order_name); | ||
500 | |||
501 | static const struct drm_prop_enum_list drm_dpms_enum_list[] = { | ||
502 | { DRM_MODE_DPMS_ON, "On" }, | ||
503 | { DRM_MODE_DPMS_STANDBY, "Standby" }, | ||
504 | { DRM_MODE_DPMS_SUSPEND, "Suspend" }, | ||
505 | { DRM_MODE_DPMS_OFF, "Off" } | ||
506 | }; | ||
507 | DRM_ENUM_NAME_FN(drm_get_dpms_name, drm_dpms_enum_list) | ||
508 | |||
509 | /** | ||
510 | * drm_display_info_set_bus_formats - set the supported bus formats | ||
511 | * @info: display info to store bus formats in | ||
512 | * @formats: array containing the supported bus formats | ||
513 | * @num_formats: the number of entries in the fmts array | ||
514 | * | ||
515 | * Store the supported bus formats in display info structure. | ||
516 | * See MEDIA_BUS_FMT_* definitions in include/uapi/linux/media-bus-format.h for | ||
517 | * a full list of available formats. | ||
518 | */ | ||
519 | int drm_display_info_set_bus_formats(struct drm_display_info *info, | ||
520 | const u32 *formats, | ||
521 | unsigned int num_formats) | ||
522 | { | ||
523 | u32 *fmts = NULL; | ||
524 | |||
525 | if (!formats && num_formats) | ||
526 | return -EINVAL; | ||
527 | |||
528 | if (formats && num_formats) { | ||
529 | fmts = kmemdup(formats, sizeof(*formats) * num_formats, | ||
530 | GFP_KERNEL); | ||
531 | if (!fmts) | ||
532 | return -ENOMEM; | ||
533 | } | ||
534 | |||
535 | kfree(info->bus_formats); | ||
536 | info->bus_formats = fmts; | ||
537 | info->num_bus_formats = num_formats; | ||
538 | |||
539 | return 0; | ||
540 | } | ||
541 | EXPORT_SYMBOL(drm_display_info_set_bus_formats); | ||
542 | |||
543 | /* Optional connector properties. */ | ||
544 | static const struct drm_prop_enum_list drm_scaling_mode_enum_list[] = { | ||
545 | { DRM_MODE_SCALE_NONE, "None" }, | ||
546 | { DRM_MODE_SCALE_FULLSCREEN, "Full" }, | ||
547 | { DRM_MODE_SCALE_CENTER, "Center" }, | ||
548 | { DRM_MODE_SCALE_ASPECT, "Full aspect" }, | ||
549 | }; | ||
550 | |||
551 | static const struct drm_prop_enum_list drm_aspect_ratio_enum_list[] = { | ||
552 | { DRM_MODE_PICTURE_ASPECT_NONE, "Automatic" }, | ||
553 | { DRM_MODE_PICTURE_ASPECT_4_3, "4:3" }, | ||
554 | { DRM_MODE_PICTURE_ASPECT_16_9, "16:9" }, | ||
555 | }; | ||
556 | |||
557 | static const struct drm_prop_enum_list drm_dvi_i_select_enum_list[] = { | ||
558 | { DRM_MODE_SUBCONNECTOR_Automatic, "Automatic" }, /* DVI-I and TV-out */ | ||
559 | { DRM_MODE_SUBCONNECTOR_DVID, "DVI-D" }, /* DVI-I */ | ||
560 | { DRM_MODE_SUBCONNECTOR_DVIA, "DVI-A" }, /* DVI-I */ | ||
561 | }; | ||
562 | DRM_ENUM_NAME_FN(drm_get_dvi_i_select_name, drm_dvi_i_select_enum_list) | ||
563 | |||
564 | static const struct drm_prop_enum_list drm_dvi_i_subconnector_enum_list[] = { | ||
565 | { DRM_MODE_SUBCONNECTOR_Unknown, "Unknown" }, /* DVI-I and TV-out */ | ||
566 | { DRM_MODE_SUBCONNECTOR_DVID, "DVI-D" }, /* DVI-I */ | ||
567 | { DRM_MODE_SUBCONNECTOR_DVIA, "DVI-A" }, /* DVI-I */ | ||
568 | }; | ||
569 | DRM_ENUM_NAME_FN(drm_get_dvi_i_subconnector_name, | ||
570 | drm_dvi_i_subconnector_enum_list) | ||
571 | |||
572 | static const struct drm_prop_enum_list drm_tv_select_enum_list[] = { | ||
573 | { DRM_MODE_SUBCONNECTOR_Automatic, "Automatic" }, /* DVI-I and TV-out */ | ||
574 | { DRM_MODE_SUBCONNECTOR_Composite, "Composite" }, /* TV-out */ | ||
575 | { DRM_MODE_SUBCONNECTOR_SVIDEO, "SVIDEO" }, /* TV-out */ | ||
576 | { DRM_MODE_SUBCONNECTOR_Component, "Component" }, /* TV-out */ | ||
577 | { DRM_MODE_SUBCONNECTOR_SCART, "SCART" }, /* TV-out */ | ||
578 | }; | ||
579 | DRM_ENUM_NAME_FN(drm_get_tv_select_name, drm_tv_select_enum_list) | ||
580 | |||
581 | static const struct drm_prop_enum_list drm_tv_subconnector_enum_list[] = { | ||
582 | { DRM_MODE_SUBCONNECTOR_Unknown, "Unknown" }, /* DVI-I and TV-out */ | ||
583 | { DRM_MODE_SUBCONNECTOR_Composite, "Composite" }, /* TV-out */ | ||
584 | { DRM_MODE_SUBCONNECTOR_SVIDEO, "SVIDEO" }, /* TV-out */ | ||
585 | { DRM_MODE_SUBCONNECTOR_Component, "Component" }, /* TV-out */ | ||
586 | { DRM_MODE_SUBCONNECTOR_SCART, "SCART" }, /* TV-out */ | ||
587 | }; | ||
588 | DRM_ENUM_NAME_FN(drm_get_tv_subconnector_name, | ||
589 | drm_tv_subconnector_enum_list) | ||
590 | |||
591 | int drm_connector_create_standard_properties(struct drm_device *dev) | ||
592 | { | ||
593 | struct drm_property *prop; | ||
594 | |||
595 | prop = drm_property_create(dev, DRM_MODE_PROP_BLOB | | ||
596 | DRM_MODE_PROP_IMMUTABLE, | ||
597 | "EDID", 0); | ||
598 | if (!prop) | ||
599 | return -ENOMEM; | ||
600 | dev->mode_config.edid_property = prop; | ||
601 | |||
602 | prop = drm_property_create_enum(dev, 0, | ||
603 | "DPMS", drm_dpms_enum_list, | ||
604 | ARRAY_SIZE(drm_dpms_enum_list)); | ||
605 | if (!prop) | ||
606 | return -ENOMEM; | ||
607 | dev->mode_config.dpms_property = prop; | ||
608 | |||
609 | prop = drm_property_create(dev, | ||
610 | DRM_MODE_PROP_BLOB | | ||
611 | DRM_MODE_PROP_IMMUTABLE, | ||
612 | "PATH", 0); | ||
613 | if (!prop) | ||
614 | return -ENOMEM; | ||
615 | dev->mode_config.path_property = prop; | ||
616 | |||
617 | prop = drm_property_create(dev, | ||
618 | DRM_MODE_PROP_BLOB | | ||
619 | DRM_MODE_PROP_IMMUTABLE, | ||
620 | "TILE", 0); | ||
621 | if (!prop) | ||
622 | return -ENOMEM; | ||
623 | dev->mode_config.tile_property = prop; | ||
624 | |||
625 | return 0; | ||
626 | } | ||
627 | |||
628 | /** | ||
629 | * drm_mode_create_dvi_i_properties - create DVI-I specific connector properties | ||
630 | * @dev: DRM device | ||
631 | * | ||
632 | * Called by a driver the first time a DVI-I connector is made. | ||
633 | */ | ||
634 | int drm_mode_create_dvi_i_properties(struct drm_device *dev) | ||
635 | { | ||
636 | struct drm_property *dvi_i_selector; | ||
637 | struct drm_property *dvi_i_subconnector; | ||
638 | |||
639 | if (dev->mode_config.dvi_i_select_subconnector_property) | ||
640 | return 0; | ||
641 | |||
642 | dvi_i_selector = | ||
643 | drm_property_create_enum(dev, 0, | ||
644 | "select subconnector", | ||
645 | drm_dvi_i_select_enum_list, | ||
646 | ARRAY_SIZE(drm_dvi_i_select_enum_list)); | ||
647 | dev->mode_config.dvi_i_select_subconnector_property = dvi_i_selector; | ||
648 | |||
649 | dvi_i_subconnector = drm_property_create_enum(dev, DRM_MODE_PROP_IMMUTABLE, | ||
650 | "subconnector", | ||
651 | drm_dvi_i_subconnector_enum_list, | ||
652 | ARRAY_SIZE(drm_dvi_i_subconnector_enum_list)); | ||
653 | dev->mode_config.dvi_i_subconnector_property = dvi_i_subconnector; | ||
654 | |||
655 | return 0; | ||
656 | } | ||
657 | EXPORT_SYMBOL(drm_mode_create_dvi_i_properties); | ||
658 | |||
659 | /** | ||
660 | * drm_create_tv_properties - create TV specific connector properties | ||
661 | * @dev: DRM device | ||
662 | * @num_modes: number of different TV formats (modes) supported | ||
663 | * @modes: array of pointers to strings containing name of each format | ||
664 | * | ||
665 | * Called by a driver's TV initialization routine, this function creates | ||
666 | * the TV specific connector properties for a given device. Caller is | ||
667 | * responsible for allocating a list of format names and passing them to | ||
668 | * this routine. | ||
669 | */ | ||
670 | int drm_mode_create_tv_properties(struct drm_device *dev, | ||
671 | unsigned int num_modes, | ||
672 | const char * const modes[]) | ||
673 | { | ||
674 | struct drm_property *tv_selector; | ||
675 | struct drm_property *tv_subconnector; | ||
676 | unsigned int i; | ||
677 | |||
678 | if (dev->mode_config.tv_select_subconnector_property) | ||
679 | return 0; | ||
680 | |||
681 | /* | ||
682 | * Basic connector properties | ||
683 | */ | ||
684 | tv_selector = drm_property_create_enum(dev, 0, | ||
685 | "select subconnector", | ||
686 | drm_tv_select_enum_list, | ||
687 | ARRAY_SIZE(drm_tv_select_enum_list)); | ||
688 | if (!tv_selector) | ||
689 | goto nomem; | ||
690 | |||
691 | dev->mode_config.tv_select_subconnector_property = tv_selector; | ||
692 | |||
693 | tv_subconnector = | ||
694 | drm_property_create_enum(dev, DRM_MODE_PROP_IMMUTABLE, | ||
695 | "subconnector", | ||
696 | drm_tv_subconnector_enum_list, | ||
697 | ARRAY_SIZE(drm_tv_subconnector_enum_list)); | ||
698 | if (!tv_subconnector) | ||
699 | goto nomem; | ||
700 | dev->mode_config.tv_subconnector_property = tv_subconnector; | ||
701 | |||
702 | /* | ||
703 | * Other, TV specific properties: margins & TV modes. | ||
704 | */ | ||
705 | dev->mode_config.tv_left_margin_property = | ||
706 | drm_property_create_range(dev, 0, "left margin", 0, 100); | ||
707 | if (!dev->mode_config.tv_left_margin_property) | ||
708 | goto nomem; | ||
709 | |||
710 | dev->mode_config.tv_right_margin_property = | ||
711 | drm_property_create_range(dev, 0, "right margin", 0, 100); | ||
712 | if (!dev->mode_config.tv_right_margin_property) | ||
713 | goto nomem; | ||
714 | |||
715 | dev->mode_config.tv_top_margin_property = | ||
716 | drm_property_create_range(dev, 0, "top margin", 0, 100); | ||
717 | if (!dev->mode_config.tv_top_margin_property) | ||
718 | goto nomem; | ||
719 | |||
720 | dev->mode_config.tv_bottom_margin_property = | ||
721 | drm_property_create_range(dev, 0, "bottom margin", 0, 100); | ||
722 | if (!dev->mode_config.tv_bottom_margin_property) | ||
723 | goto nomem; | ||
724 | |||
725 | dev->mode_config.tv_mode_property = | ||
726 | drm_property_create(dev, DRM_MODE_PROP_ENUM, | ||
727 | "mode", num_modes); | ||
728 | if (!dev->mode_config.tv_mode_property) | ||
729 | goto nomem; | ||
730 | |||
731 | for (i = 0; i < num_modes; i++) | ||
732 | drm_property_add_enum(dev->mode_config.tv_mode_property, i, | ||
733 | i, modes[i]); | ||
734 | |||
735 | dev->mode_config.tv_brightness_property = | ||
736 | drm_property_create_range(dev, 0, "brightness", 0, 100); | ||
737 | if (!dev->mode_config.tv_brightness_property) | ||
738 | goto nomem; | ||
739 | |||
740 | dev->mode_config.tv_contrast_property = | ||
741 | drm_property_create_range(dev, 0, "contrast", 0, 100); | ||
742 | if (!dev->mode_config.tv_contrast_property) | ||
743 | goto nomem; | ||
744 | |||
745 | dev->mode_config.tv_flicker_reduction_property = | ||
746 | drm_property_create_range(dev, 0, "flicker reduction", 0, 100); | ||
747 | if (!dev->mode_config.tv_flicker_reduction_property) | ||
748 | goto nomem; | ||
749 | |||
750 | dev->mode_config.tv_overscan_property = | ||
751 | drm_property_create_range(dev, 0, "overscan", 0, 100); | ||
752 | if (!dev->mode_config.tv_overscan_property) | ||
753 | goto nomem; | ||
754 | |||
755 | dev->mode_config.tv_saturation_property = | ||
756 | drm_property_create_range(dev, 0, "saturation", 0, 100); | ||
757 | if (!dev->mode_config.tv_saturation_property) | ||
758 | goto nomem; | ||
759 | |||
760 | dev->mode_config.tv_hue_property = | ||
761 | drm_property_create_range(dev, 0, "hue", 0, 100); | ||
762 | if (!dev->mode_config.tv_hue_property) | ||
763 | goto nomem; | ||
764 | |||
765 | return 0; | ||
766 | nomem: | ||
767 | return -ENOMEM; | ||
768 | } | ||
769 | EXPORT_SYMBOL(drm_mode_create_tv_properties); | ||
770 | |||
771 | /** | ||
772 | * drm_mode_create_scaling_mode_property - create scaling mode property | ||
773 | * @dev: DRM device | ||
774 | * | ||
775 | * Called by a driver the first time it's needed, must be attached to desired | ||
776 | * connectors. | ||
777 | */ | ||
778 | int drm_mode_create_scaling_mode_property(struct drm_device *dev) | ||
779 | { | ||
780 | struct drm_property *scaling_mode; | ||
781 | |||
782 | if (dev->mode_config.scaling_mode_property) | ||
783 | return 0; | ||
784 | |||
785 | scaling_mode = | ||
786 | drm_property_create_enum(dev, 0, "scaling mode", | ||
787 | drm_scaling_mode_enum_list, | ||
788 | ARRAY_SIZE(drm_scaling_mode_enum_list)); | ||
789 | |||
790 | dev->mode_config.scaling_mode_property = scaling_mode; | ||
791 | |||
792 | return 0; | ||
793 | } | ||
794 | EXPORT_SYMBOL(drm_mode_create_scaling_mode_property); | ||
795 | |||
796 | /** | ||
797 | * drm_mode_create_aspect_ratio_property - create aspect ratio property | ||
798 | * @dev: DRM device | ||
799 | * | ||
800 | * Called by a driver the first time it's needed, must be attached to desired | ||
801 | * connectors. | ||
802 | * | ||
803 | * Returns: | ||
804 | * Zero on success, negative errno on failure. | ||
805 | */ | ||
806 | int drm_mode_create_aspect_ratio_property(struct drm_device *dev) | ||
807 | { | ||
808 | if (dev->mode_config.aspect_ratio_property) | ||
809 | return 0; | ||
810 | |||
811 | dev->mode_config.aspect_ratio_property = | ||
812 | drm_property_create_enum(dev, 0, "aspect ratio", | ||
813 | drm_aspect_ratio_enum_list, | ||
814 | ARRAY_SIZE(drm_aspect_ratio_enum_list)); | ||
815 | |||
816 | if (dev->mode_config.aspect_ratio_property == NULL) | ||
817 | return -ENOMEM; | ||
818 | |||
819 | return 0; | ||
820 | } | ||
821 | EXPORT_SYMBOL(drm_mode_create_aspect_ratio_property); | ||
822 | |||
823 | /** | ||
824 | * drm_mode_create_suggested_offset_properties - create suggests offset properties | ||
825 | * @dev: DRM device | ||
826 | * | ||
827 | * Create the the suggested x/y offset property for connectors. | ||
828 | */ | ||
829 | int drm_mode_create_suggested_offset_properties(struct drm_device *dev) | ||
830 | { | ||
831 | if (dev->mode_config.suggested_x_property && dev->mode_config.suggested_y_property) | ||
832 | return 0; | ||
833 | |||
834 | dev->mode_config.suggested_x_property = | ||
835 | drm_property_create_range(dev, DRM_MODE_PROP_IMMUTABLE, "suggested X", 0, 0xffffffff); | ||
836 | |||
837 | dev->mode_config.suggested_y_property = | ||
838 | drm_property_create_range(dev, DRM_MODE_PROP_IMMUTABLE, "suggested Y", 0, 0xffffffff); | ||
839 | |||
840 | if (dev->mode_config.suggested_x_property == NULL || | ||
841 | dev->mode_config.suggested_y_property == NULL) | ||
842 | return -ENOMEM; | ||
843 | return 0; | ||
844 | } | ||
845 | EXPORT_SYMBOL(drm_mode_create_suggested_offset_properties); | ||
846 | |||
847 | /** | ||
848 | * drm_mode_connector_set_path_property - set tile property on connector | ||
849 | * @connector: connector to set property on. | ||
850 | * @path: path to use for property; must not be NULL. | ||
851 | * | ||
852 | * This creates a property to expose to userspace to specify a | ||
853 | * connector path. This is mainly used for DisplayPort MST where | ||
854 | * connectors have a topology and we want to allow userspace to give | ||
855 | * them more meaningful names. | ||
856 | * | ||
857 | * Returns: | ||
858 | * Zero on success, negative errno on failure. | ||
859 | */ | ||
860 | int drm_mode_connector_set_path_property(struct drm_connector *connector, | ||
861 | const char *path) | ||
862 | { | ||
863 | struct drm_device *dev = connector->dev; | ||
864 | int ret; | ||
865 | |||
866 | ret = drm_property_replace_global_blob(dev, | ||
867 | &connector->path_blob_ptr, | ||
868 | strlen(path) + 1, | ||
869 | path, | ||
870 | &connector->base, | ||
871 | dev->mode_config.path_property); | ||
872 | return ret; | ||
873 | } | ||
874 | EXPORT_SYMBOL(drm_mode_connector_set_path_property); | ||
875 | |||
876 | /** | ||
877 | * drm_mode_connector_set_tile_property - set tile property on connector | ||
878 | * @connector: connector to set property on. | ||
879 | * | ||
880 | * This looks up the tile information for a connector, and creates a | ||
881 | * property for userspace to parse if it exists. The property is of | ||
882 | * the form of 8 integers using ':' as a separator. | ||
883 | * | ||
884 | * Returns: | ||
885 | * Zero on success, errno on failure. | ||
886 | */ | ||
887 | int drm_mode_connector_set_tile_property(struct drm_connector *connector) | ||
888 | { | ||
889 | struct drm_device *dev = connector->dev; | ||
890 | char tile[256]; | ||
891 | int ret; | ||
892 | |||
893 | if (!connector->has_tile) { | ||
894 | ret = drm_property_replace_global_blob(dev, | ||
895 | &connector->tile_blob_ptr, | ||
896 | 0, | ||
897 | NULL, | ||
898 | &connector->base, | ||
899 | dev->mode_config.tile_property); | ||
900 | return ret; | ||
901 | } | ||
902 | |||
903 | snprintf(tile, 256, "%d:%d:%d:%d:%d:%d:%d:%d", | ||
904 | connector->tile_group->id, connector->tile_is_single_monitor, | ||
905 | connector->num_h_tile, connector->num_v_tile, | ||
906 | connector->tile_h_loc, connector->tile_v_loc, | ||
907 | connector->tile_h_size, connector->tile_v_size); | ||
908 | |||
909 | ret = drm_property_replace_global_blob(dev, | ||
910 | &connector->tile_blob_ptr, | ||
911 | strlen(tile) + 1, | ||
912 | tile, | ||
913 | &connector->base, | ||
914 | dev->mode_config.tile_property); | ||
915 | return ret; | ||
916 | } | ||
917 | EXPORT_SYMBOL(drm_mode_connector_set_tile_property); | ||
918 | |||
919 | /** | ||
920 | * drm_mode_connector_update_edid_property - update the edid property of a connector | ||
921 | * @connector: drm connector | ||
922 | * @edid: new value of the edid property | ||
923 | * | ||
924 | * This function creates a new blob modeset object and assigns its id to the | ||
925 | * connector's edid property. | ||
926 | * | ||
927 | * Returns: | ||
928 | * Zero on success, negative errno on failure. | ||
929 | */ | ||
930 | int drm_mode_connector_update_edid_property(struct drm_connector *connector, | ||
931 | const struct edid *edid) | ||
932 | { | ||
933 | struct drm_device *dev = connector->dev; | ||
934 | size_t size = 0; | ||
935 | int ret; | ||
936 | |||
937 | /* ignore requests to set edid when overridden */ | ||
938 | if (connector->override_edid) | ||
939 | return 0; | ||
940 | |||
941 | if (edid) | ||
942 | size = EDID_LENGTH * (1 + edid->extensions); | ||
943 | |||
944 | ret = drm_property_replace_global_blob(dev, | ||
945 | &connector->edid_blob_ptr, | ||
946 | size, | ||
947 | edid, | ||
948 | &connector->base, | ||
949 | dev->mode_config.edid_property); | ||
950 | return ret; | ||
951 | } | ||
952 | EXPORT_SYMBOL(drm_mode_connector_update_edid_property); | ||
953 | |||
954 | int drm_mode_connector_set_obj_prop(struct drm_mode_object *obj, | ||
955 | struct drm_property *property, | ||
956 | uint64_t value) | ||
957 | { | ||
958 | int ret = -EINVAL; | ||
959 | struct drm_connector *connector = obj_to_connector(obj); | ||
960 | |||
961 | /* Do DPMS ourselves */ | ||
962 | if (property == connector->dev->mode_config.dpms_property) { | ||
963 | ret = (*connector->funcs->dpms)(connector, (int)value); | ||
964 | } else if (connector->funcs->set_property) | ||
965 | ret = connector->funcs->set_property(connector, property, value); | ||
966 | |||
967 | /* store the property value if successful */ | ||
968 | if (!ret) | ||
969 | drm_object_property_set_value(&connector->base, property, value); | ||
970 | return ret; | ||
971 | } | ||
972 | |||
973 | int drm_mode_connector_property_set_ioctl(struct drm_device *dev, | ||
974 | void *data, struct drm_file *file_priv) | ||
975 | { | ||
976 | struct drm_mode_connector_set_property *conn_set_prop = data; | ||
977 | struct drm_mode_obj_set_property obj_set_prop = { | ||
978 | .value = conn_set_prop->value, | ||
979 | .prop_id = conn_set_prop->prop_id, | ||
980 | .obj_id = conn_set_prop->connector_id, | ||
981 | .obj_type = DRM_MODE_OBJECT_CONNECTOR | ||
982 | }; | ||
983 | |||
984 | /* It does all the locking and checking we need */ | ||
985 | return drm_mode_obj_set_property_ioctl(dev, &obj_set_prop, file_priv); | ||
986 | } | ||
987 | |||
988 | static struct drm_encoder *drm_connector_get_encoder(struct drm_connector *connector) | ||
989 | { | ||
990 | /* For atomic drivers only state objects are synchronously updated and | ||
991 | * protected by modeset locks, so check those first. */ | ||
992 | if (connector->state) | ||
993 | return connector->state->best_encoder; | ||
994 | return connector->encoder; | ||
995 | } | ||
996 | |||
997 | static bool drm_mode_expose_to_userspace(const struct drm_display_mode *mode, | ||
998 | const struct drm_file *file_priv) | ||
999 | { | ||
1000 | /* | ||
1001 | * If user-space hasn't configured the driver to expose the stereo 3D | ||
1002 | * modes, don't expose them. | ||
1003 | */ | ||
1004 | if (!file_priv->stereo_allowed && drm_mode_is_stereo(mode)) | ||
1005 | return false; | ||
1006 | |||
1007 | return true; | ||
1008 | } | ||
1009 | |||
1010 | int drm_mode_getconnector(struct drm_device *dev, void *data, | ||
1011 | struct drm_file *file_priv) | ||
1012 | { | ||
1013 | struct drm_mode_get_connector *out_resp = data; | ||
1014 | struct drm_connector *connector; | ||
1015 | struct drm_encoder *encoder; | ||
1016 | struct drm_display_mode *mode; | ||
1017 | int mode_count = 0; | ||
1018 | int encoders_count = 0; | ||
1019 | int ret = 0; | ||
1020 | int copied = 0; | ||
1021 | int i; | ||
1022 | struct drm_mode_modeinfo u_mode; | ||
1023 | struct drm_mode_modeinfo __user *mode_ptr; | ||
1024 | uint32_t __user *encoder_ptr; | ||
1025 | |||
1026 | if (!drm_core_check_feature(dev, DRIVER_MODESET)) | ||
1027 | return -EINVAL; | ||
1028 | |||
1029 | memset(&u_mode, 0, sizeof(struct drm_mode_modeinfo)); | ||
1030 | |||
1031 | mutex_lock(&dev->mode_config.mutex); | ||
1032 | |||
1033 | connector = drm_connector_lookup(dev, out_resp->connector_id); | ||
1034 | if (!connector) { | ||
1035 | ret = -ENOENT; | ||
1036 | goto out_unlock; | ||
1037 | } | ||
1038 | |||
1039 | for (i = 0; i < DRM_CONNECTOR_MAX_ENCODER; i++) | ||
1040 | if (connector->encoder_ids[i] != 0) | ||
1041 | encoders_count++; | ||
1042 | |||
1043 | if (out_resp->count_modes == 0) { | ||
1044 | connector->funcs->fill_modes(connector, | ||
1045 | dev->mode_config.max_width, | ||
1046 | dev->mode_config.max_height); | ||
1047 | } | ||
1048 | |||
1049 | /* delayed so we get modes regardless of pre-fill_modes state */ | ||
1050 | list_for_each_entry(mode, &connector->modes, head) | ||
1051 | if (drm_mode_expose_to_userspace(mode, file_priv)) | ||
1052 | mode_count++; | ||
1053 | |||
1054 | out_resp->connector_id = connector->base.id; | ||
1055 | out_resp->connector_type = connector->connector_type; | ||
1056 | out_resp->connector_type_id = connector->connector_type_id; | ||
1057 | out_resp->mm_width = connector->display_info.width_mm; | ||
1058 | out_resp->mm_height = connector->display_info.height_mm; | ||
1059 | out_resp->subpixel = connector->display_info.subpixel_order; | ||
1060 | out_resp->connection = connector->status; | ||
1061 | |||
1062 | drm_modeset_lock(&dev->mode_config.connection_mutex, NULL); | ||
1063 | encoder = drm_connector_get_encoder(connector); | ||
1064 | if (encoder) | ||
1065 | out_resp->encoder_id = encoder->base.id; | ||
1066 | else | ||
1067 | out_resp->encoder_id = 0; | ||
1068 | |||
1069 | /* | ||
1070 | * This ioctl is called twice, once to determine how much space is | ||
1071 | * needed, and the 2nd time to fill it. | ||
1072 | */ | ||
1073 | if ((out_resp->count_modes >= mode_count) && mode_count) { | ||
1074 | copied = 0; | ||
1075 | mode_ptr = (struct drm_mode_modeinfo __user *)(unsigned long)out_resp->modes_ptr; | ||
1076 | list_for_each_entry(mode, &connector->modes, head) { | ||
1077 | if (!drm_mode_expose_to_userspace(mode, file_priv)) | ||
1078 | continue; | ||
1079 | |||
1080 | drm_mode_convert_to_umode(&u_mode, mode); | ||
1081 | if (copy_to_user(mode_ptr + copied, | ||
1082 | &u_mode, sizeof(u_mode))) { | ||
1083 | ret = -EFAULT; | ||
1084 | goto out; | ||
1085 | } | ||
1086 | copied++; | ||
1087 | } | ||
1088 | } | ||
1089 | out_resp->count_modes = mode_count; | ||
1090 | |||
1091 | ret = drm_mode_object_get_properties(&connector->base, file_priv->atomic, | ||
1092 | (uint32_t __user *)(unsigned long)(out_resp->props_ptr), | ||
1093 | (uint64_t __user *)(unsigned long)(out_resp->prop_values_ptr), | ||
1094 | &out_resp->count_props); | ||
1095 | if (ret) | ||
1096 | goto out; | ||
1097 | |||
1098 | if ((out_resp->count_encoders >= encoders_count) && encoders_count) { | ||
1099 | copied = 0; | ||
1100 | encoder_ptr = (uint32_t __user *)(unsigned long)(out_resp->encoders_ptr); | ||
1101 | for (i = 0; i < DRM_CONNECTOR_MAX_ENCODER; i++) { | ||
1102 | if (connector->encoder_ids[i] != 0) { | ||
1103 | if (put_user(connector->encoder_ids[i], | ||
1104 | encoder_ptr + copied)) { | ||
1105 | ret = -EFAULT; | ||
1106 | goto out; | ||
1107 | } | ||
1108 | copied++; | ||
1109 | } | ||
1110 | } | ||
1111 | } | ||
1112 | out_resp->count_encoders = encoders_count; | ||
1113 | |||
1114 | out: | ||
1115 | drm_modeset_unlock(&dev->mode_config.connection_mutex); | ||
1116 | |||
1117 | drm_connector_unreference(connector); | ||
1118 | out_unlock: | ||
1119 | mutex_unlock(&dev->mode_config.mutex); | ||
1120 | |||
1121 | return ret; | ||
1122 | } | ||
1123 | |||
diff --git a/drivers/gpu/drm/drm_crtc.c b/drivers/gpu/drm/drm_crtc.c index e92bb9d3f90f..7f2510524f09 100644 --- a/drivers/gpu/drm/drm_crtc.c +++ b/drivers/gpu/drm/drm_crtc.c | |||
@@ -40,138 +40,20 @@ | |||
40 | #include <drm/drm_modeset_lock.h> | 40 | #include <drm/drm_modeset_lock.h> |
41 | #include <drm/drm_atomic.h> | 41 | #include <drm/drm_atomic.h> |
42 | #include <drm/drm_auth.h> | 42 | #include <drm/drm_auth.h> |
43 | #include <drm/drm_framebuffer.h> | ||
43 | 44 | ||
44 | #include "drm_crtc_internal.h" | 45 | #include "drm_crtc_internal.h" |
45 | #include "drm_internal.h" | 46 | #include "drm_internal.h" |
46 | 47 | ||
47 | static struct drm_framebuffer * | ||
48 | internal_framebuffer_create(struct drm_device *dev, | ||
49 | const struct drm_mode_fb_cmd2 *r, | ||
50 | struct drm_file *file_priv); | ||
51 | |||
52 | /* Avoid boilerplate. I'm tired of typing. */ | ||
53 | #define DRM_ENUM_NAME_FN(fnname, list) \ | ||
54 | const char *fnname(int val) \ | ||
55 | { \ | ||
56 | int i; \ | ||
57 | for (i = 0; i < ARRAY_SIZE(list); i++) { \ | ||
58 | if (list[i].type == val) \ | ||
59 | return list[i].name; \ | ||
60 | } \ | ||
61 | return "(unknown)"; \ | ||
62 | } | ||
63 | |||
64 | /* | 48 | /* |
65 | * Global properties | 49 | * Global properties |
66 | */ | 50 | */ |
67 | static const struct drm_prop_enum_list drm_dpms_enum_list[] = { | ||
68 | { DRM_MODE_DPMS_ON, "On" }, | ||
69 | { DRM_MODE_DPMS_STANDBY, "Standby" }, | ||
70 | { DRM_MODE_DPMS_SUSPEND, "Suspend" }, | ||
71 | { DRM_MODE_DPMS_OFF, "Off" } | ||
72 | }; | ||
73 | |||
74 | DRM_ENUM_NAME_FN(drm_get_dpms_name, drm_dpms_enum_list) | ||
75 | |||
76 | static const struct drm_prop_enum_list drm_plane_type_enum_list[] = { | 51 | static const struct drm_prop_enum_list drm_plane_type_enum_list[] = { |
77 | { DRM_PLANE_TYPE_OVERLAY, "Overlay" }, | 52 | { DRM_PLANE_TYPE_OVERLAY, "Overlay" }, |
78 | { DRM_PLANE_TYPE_PRIMARY, "Primary" }, | 53 | { DRM_PLANE_TYPE_PRIMARY, "Primary" }, |
79 | { DRM_PLANE_TYPE_CURSOR, "Cursor" }, | 54 | { DRM_PLANE_TYPE_CURSOR, "Cursor" }, |
80 | }; | 55 | }; |
81 | 56 | ||
82 | /* | ||
83 | * Optional properties | ||
84 | */ | ||
85 | static const struct drm_prop_enum_list drm_scaling_mode_enum_list[] = { | ||
86 | { DRM_MODE_SCALE_NONE, "None" }, | ||
87 | { DRM_MODE_SCALE_FULLSCREEN, "Full" }, | ||
88 | { DRM_MODE_SCALE_CENTER, "Center" }, | ||
89 | { DRM_MODE_SCALE_ASPECT, "Full aspect" }, | ||
90 | }; | ||
91 | |||
92 | static const struct drm_prop_enum_list drm_aspect_ratio_enum_list[] = { | ||
93 | { DRM_MODE_PICTURE_ASPECT_NONE, "Automatic" }, | ||
94 | { DRM_MODE_PICTURE_ASPECT_4_3, "4:3" }, | ||
95 | { DRM_MODE_PICTURE_ASPECT_16_9, "16:9" }, | ||
96 | }; | ||
97 | |||
98 | /* | ||
99 | * Non-global properties, but "required" for certain connectors. | ||
100 | */ | ||
101 | static const struct drm_prop_enum_list drm_dvi_i_select_enum_list[] = { | ||
102 | { DRM_MODE_SUBCONNECTOR_Automatic, "Automatic" }, /* DVI-I and TV-out */ | ||
103 | { DRM_MODE_SUBCONNECTOR_DVID, "DVI-D" }, /* DVI-I */ | ||
104 | { DRM_MODE_SUBCONNECTOR_DVIA, "DVI-A" }, /* DVI-I */ | ||
105 | }; | ||
106 | |||
107 | DRM_ENUM_NAME_FN(drm_get_dvi_i_select_name, drm_dvi_i_select_enum_list) | ||
108 | |||
109 | static const struct drm_prop_enum_list drm_dvi_i_subconnector_enum_list[] = { | ||
110 | { DRM_MODE_SUBCONNECTOR_Unknown, "Unknown" }, /* DVI-I and TV-out */ | ||
111 | { DRM_MODE_SUBCONNECTOR_DVID, "DVI-D" }, /* DVI-I */ | ||
112 | { DRM_MODE_SUBCONNECTOR_DVIA, "DVI-A" }, /* DVI-I */ | ||
113 | }; | ||
114 | |||
115 | DRM_ENUM_NAME_FN(drm_get_dvi_i_subconnector_name, | ||
116 | drm_dvi_i_subconnector_enum_list) | ||
117 | |||
118 | static const struct drm_prop_enum_list drm_tv_select_enum_list[] = { | ||
119 | { DRM_MODE_SUBCONNECTOR_Automatic, "Automatic" }, /* DVI-I and TV-out */ | ||
120 | { DRM_MODE_SUBCONNECTOR_Composite, "Composite" }, /* TV-out */ | ||
121 | { DRM_MODE_SUBCONNECTOR_SVIDEO, "SVIDEO" }, /* TV-out */ | ||
122 | { DRM_MODE_SUBCONNECTOR_Component, "Component" }, /* TV-out */ | ||
123 | { DRM_MODE_SUBCONNECTOR_SCART, "SCART" }, /* TV-out */ | ||
124 | }; | ||
125 | |||
126 | DRM_ENUM_NAME_FN(drm_get_tv_select_name, drm_tv_select_enum_list) | ||
127 | |||
128 | static const struct drm_prop_enum_list drm_tv_subconnector_enum_list[] = { | ||
129 | { DRM_MODE_SUBCONNECTOR_Unknown, "Unknown" }, /* DVI-I and TV-out */ | ||
130 | { DRM_MODE_SUBCONNECTOR_Composite, "Composite" }, /* TV-out */ | ||
131 | { DRM_MODE_SUBCONNECTOR_SVIDEO, "SVIDEO" }, /* TV-out */ | ||
132 | { DRM_MODE_SUBCONNECTOR_Component, "Component" }, /* TV-out */ | ||
133 | { DRM_MODE_SUBCONNECTOR_SCART, "SCART" }, /* TV-out */ | ||
134 | }; | ||
135 | |||
136 | DRM_ENUM_NAME_FN(drm_get_tv_subconnector_name, | ||
137 | drm_tv_subconnector_enum_list) | ||
138 | |||
139 | static const struct drm_prop_enum_list drm_dirty_info_enum_list[] = { | ||
140 | { DRM_MODE_DIRTY_OFF, "Off" }, | ||
141 | { DRM_MODE_DIRTY_ON, "On" }, | ||
142 | { DRM_MODE_DIRTY_ANNOTATE, "Annotate" }, | ||
143 | }; | ||
144 | |||
145 | struct drm_conn_prop_enum_list { | ||
146 | int type; | ||
147 | const char *name; | ||
148 | struct ida ida; | ||
149 | }; | ||
150 | |||
151 | /* | ||
152 | * Connector and encoder types. | ||
153 | */ | ||
154 | static struct drm_conn_prop_enum_list drm_connector_enum_list[] = { | ||
155 | { DRM_MODE_CONNECTOR_Unknown, "Unknown" }, | ||
156 | { DRM_MODE_CONNECTOR_VGA, "VGA" }, | ||
157 | { DRM_MODE_CONNECTOR_DVII, "DVI-I" }, | ||
158 | { DRM_MODE_CONNECTOR_DVID, "DVI-D" }, | ||
159 | { DRM_MODE_CONNECTOR_DVIA, "DVI-A" }, | ||
160 | { DRM_MODE_CONNECTOR_Composite, "Composite" }, | ||
161 | { DRM_MODE_CONNECTOR_SVIDEO, "SVIDEO" }, | ||
162 | { DRM_MODE_CONNECTOR_LVDS, "LVDS" }, | ||
163 | { DRM_MODE_CONNECTOR_Component, "Component" }, | ||
164 | { DRM_MODE_CONNECTOR_9PinDIN, "DIN" }, | ||
165 | { DRM_MODE_CONNECTOR_DisplayPort, "DP" }, | ||
166 | { DRM_MODE_CONNECTOR_HDMIA, "HDMI-A" }, | ||
167 | { DRM_MODE_CONNECTOR_HDMIB, "HDMI-B" }, | ||
168 | { DRM_MODE_CONNECTOR_TV, "TV" }, | ||
169 | { DRM_MODE_CONNECTOR_eDP, "eDP" }, | ||
170 | { DRM_MODE_CONNECTOR_VIRTUAL, "Virtual" }, | ||
171 | { DRM_MODE_CONNECTOR_DSI, "DSI" }, | ||
172 | { DRM_MODE_CONNECTOR_DPI, "DPI" }, | ||
173 | }; | ||
174 | |||
175 | static const struct drm_prop_enum_list drm_encoder_enum_list[] = { | 57 | static const struct drm_prop_enum_list drm_encoder_enum_list[] = { |
176 | { DRM_MODE_ENCODER_NONE, "None" }, | 58 | { DRM_MODE_ENCODER_NONE, "None" }, |
177 | { DRM_MODE_ENCODER_DAC, "DAC" }, | 59 | { DRM_MODE_ENCODER_DAC, "DAC" }, |
@@ -184,71 +66,18 @@ static const struct drm_prop_enum_list drm_encoder_enum_list[] = { | |||
184 | { DRM_MODE_ENCODER_DPI, "DPI" }, | 66 | { DRM_MODE_ENCODER_DPI, "DPI" }, |
185 | }; | 67 | }; |
186 | 68 | ||
187 | static const struct drm_prop_enum_list drm_subpixel_enum_list[] = { | 69 | /* |
188 | { SubPixelUnknown, "Unknown" }, | 70 | * Optional properties |
189 | { SubPixelHorizontalRGB, "Horizontal RGB" }, | ||
190 | { SubPixelHorizontalBGR, "Horizontal BGR" }, | ||
191 | { SubPixelVerticalRGB, "Vertical RGB" }, | ||
192 | { SubPixelVerticalBGR, "Vertical BGR" }, | ||
193 | { SubPixelNone, "None" }, | ||
194 | }; | ||
195 | |||
196 | void drm_connector_ida_init(void) | ||
197 | { | ||
198 | int i; | ||
199 | |||
200 | for (i = 0; i < ARRAY_SIZE(drm_connector_enum_list); i++) | ||
201 | ida_init(&drm_connector_enum_list[i].ida); | ||
202 | } | ||
203 | |||
204 | void drm_connector_ida_destroy(void) | ||
205 | { | ||
206 | int i; | ||
207 | |||
208 | for (i = 0; i < ARRAY_SIZE(drm_connector_enum_list); i++) | ||
209 | ida_destroy(&drm_connector_enum_list[i].ida); | ||
210 | } | ||
211 | |||
212 | /** | ||
213 | * drm_get_connector_status_name - return a string for connector status | ||
214 | * @status: connector status to compute name of | ||
215 | * | ||
216 | * In contrast to the other drm_get_*_name functions this one here returns a | ||
217 | * const pointer and hence is threadsafe. | ||
218 | */ | ||
219 | const char *drm_get_connector_status_name(enum drm_connector_status status) | ||
220 | { | ||
221 | if (status == connector_status_connected) | ||
222 | return "connected"; | ||
223 | else if (status == connector_status_disconnected) | ||
224 | return "disconnected"; | ||
225 | else | ||
226 | return "unknown"; | ||
227 | } | ||
228 | EXPORT_SYMBOL(drm_get_connector_status_name); | ||
229 | |||
230 | /** | ||
231 | * drm_get_subpixel_order_name - return a string for a given subpixel enum | ||
232 | * @order: enum of subpixel_order | ||
233 | * | ||
234 | * Note you could abuse this and return something out of bounds, but that | ||
235 | * would be a caller error. No unscrubbed user data should make it here. | ||
236 | */ | 71 | */ |
237 | const char *drm_get_subpixel_order_name(enum subpixel_order order) | ||
238 | { | ||
239 | return drm_subpixel_enum_list[order].name; | ||
240 | } | ||
241 | EXPORT_SYMBOL(drm_get_subpixel_order_name); | ||
242 | |||
243 | /* | 72 | /* |
244 | * Internal function to assign a slot in the object idr and optionally | 73 | * Internal function to assign a slot in the object idr and optionally |
245 | * register the object into the idr. | 74 | * register the object into the idr. |
246 | */ | 75 | */ |
247 | static int drm_mode_object_get_reg(struct drm_device *dev, | 76 | int drm_mode_object_get_reg(struct drm_device *dev, |
248 | struct drm_mode_object *obj, | 77 | struct drm_mode_object *obj, |
249 | uint32_t obj_type, | 78 | uint32_t obj_type, |
250 | bool register_obj, | 79 | bool register_obj, |
251 | void (*obj_free_cb)(struct kref *kref)) | 80 | void (*obj_free_cb)(struct kref *kref)) |
252 | { | 81 | { |
253 | int ret; | 82 | int ret; |
254 | 83 | ||
@@ -291,8 +120,8 @@ int drm_mode_object_get(struct drm_device *dev, | |||
291 | return drm_mode_object_get_reg(dev, obj, obj_type, true, NULL); | 120 | return drm_mode_object_get_reg(dev, obj, obj_type, true, NULL); |
292 | } | 121 | } |
293 | 122 | ||
294 | static void drm_mode_object_register(struct drm_device *dev, | 123 | void drm_mode_object_register(struct drm_device *dev, |
295 | struct drm_mode_object *obj) | 124 | struct drm_mode_object *obj) |
296 | { | 125 | { |
297 | mutex_lock(&dev->mode_config.idr_mutex); | 126 | mutex_lock(&dev->mode_config.idr_mutex); |
298 | idr_replace(&dev->mode_config.crtc_idr, obj, obj->id); | 127 | idr_replace(&dev->mode_config.crtc_idr, obj, obj->id); |
@@ -321,8 +150,8 @@ void drm_mode_object_unregister(struct drm_device *dev, | |||
321 | mutex_unlock(&dev->mode_config.idr_mutex); | 150 | mutex_unlock(&dev->mode_config.idr_mutex); |
322 | } | 151 | } |
323 | 152 | ||
324 | static struct drm_mode_object *_object_find(struct drm_device *dev, | 153 | struct drm_mode_object *__drm_mode_object_find(struct drm_device *dev, |
325 | uint32_t id, uint32_t type) | 154 | uint32_t id, uint32_t type) |
326 | { | 155 | { |
327 | struct drm_mode_object *obj = NULL; | 156 | struct drm_mode_object *obj = NULL; |
328 | 157 | ||
@@ -357,7 +186,7 @@ struct drm_mode_object *drm_mode_object_find(struct drm_device *dev, | |||
357 | { | 186 | { |
358 | struct drm_mode_object *obj = NULL; | 187 | struct drm_mode_object *obj = NULL; |
359 | 188 | ||
360 | obj = _object_find(dev, id, type); | 189 | obj = __drm_mode_object_find(dev, id, type); |
361 | return obj; | 190 | return obj; |
362 | } | 191 | } |
363 | EXPORT_SYMBOL(drm_mode_object_find); | 192 | EXPORT_SYMBOL(drm_mode_object_find); |
@@ -441,199 +270,6 @@ out: | |||
441 | } | 270 | } |
442 | EXPORT_SYMBOL(drm_crtc_force_disable_all); | 271 | EXPORT_SYMBOL(drm_crtc_force_disable_all); |
443 | 272 | ||
444 | static void drm_framebuffer_free(struct kref *kref) | ||
445 | { | ||
446 | struct drm_framebuffer *fb = | ||
447 | container_of(kref, struct drm_framebuffer, base.refcount); | ||
448 | struct drm_device *dev = fb->dev; | ||
449 | |||
450 | /* | ||
451 | * The lookup idr holds a weak reference, which has not necessarily been | ||
452 | * removed at this point. Check for that. | ||
453 | */ | ||
454 | drm_mode_object_unregister(dev, &fb->base); | ||
455 | |||
456 | fb->funcs->destroy(fb); | ||
457 | } | ||
458 | |||
459 | /** | ||
460 | * drm_framebuffer_init - initialize a framebuffer | ||
461 | * @dev: DRM device | ||
462 | * @fb: framebuffer to be initialized | ||
463 | * @funcs: ... with these functions | ||
464 | * | ||
465 | * Allocates an ID for the framebuffer's parent mode object, sets its mode | ||
466 | * functions & device file and adds it to the master fd list. | ||
467 | * | ||
468 | * IMPORTANT: | ||
469 | * This functions publishes the fb and makes it available for concurrent access | ||
470 | * by other users. Which means by this point the fb _must_ be fully set up - | ||
471 | * since all the fb attributes are invariant over its lifetime, no further | ||
472 | * locking but only correct reference counting is required. | ||
473 | * | ||
474 | * Returns: | ||
475 | * Zero on success, error code on failure. | ||
476 | */ | ||
477 | int drm_framebuffer_init(struct drm_device *dev, struct drm_framebuffer *fb, | ||
478 | const struct drm_framebuffer_funcs *funcs) | ||
479 | { | ||
480 | int ret; | ||
481 | |||
482 | INIT_LIST_HEAD(&fb->filp_head); | ||
483 | fb->dev = dev; | ||
484 | fb->funcs = funcs; | ||
485 | |||
486 | ret = drm_mode_object_get_reg(dev, &fb->base, DRM_MODE_OBJECT_FB, | ||
487 | false, drm_framebuffer_free); | ||
488 | if (ret) | ||
489 | goto out; | ||
490 | |||
491 | mutex_lock(&dev->mode_config.fb_lock); | ||
492 | dev->mode_config.num_fb++; | ||
493 | list_add(&fb->head, &dev->mode_config.fb_list); | ||
494 | mutex_unlock(&dev->mode_config.fb_lock); | ||
495 | |||
496 | drm_mode_object_register(dev, &fb->base); | ||
497 | out: | ||
498 | return ret; | ||
499 | } | ||
500 | EXPORT_SYMBOL(drm_framebuffer_init); | ||
501 | |||
502 | /** | ||
503 | * drm_framebuffer_lookup - look up a drm framebuffer and grab a reference | ||
504 | * @dev: drm device | ||
505 | * @id: id of the fb object | ||
506 | * | ||
507 | * If successful, this grabs an additional reference to the framebuffer - | ||
508 | * callers need to make sure to eventually unreference the returned framebuffer | ||
509 | * again, using @drm_framebuffer_unreference. | ||
510 | */ | ||
511 | struct drm_framebuffer *drm_framebuffer_lookup(struct drm_device *dev, | ||
512 | uint32_t id) | ||
513 | { | ||
514 | struct drm_mode_object *obj; | ||
515 | struct drm_framebuffer *fb = NULL; | ||
516 | |||
517 | obj = _object_find(dev, id, DRM_MODE_OBJECT_FB); | ||
518 | if (obj) | ||
519 | fb = obj_to_fb(obj); | ||
520 | return fb; | ||
521 | } | ||
522 | EXPORT_SYMBOL(drm_framebuffer_lookup); | ||
523 | |||
524 | /** | ||
525 | * drm_framebuffer_unregister_private - unregister a private fb from the lookup idr | ||
526 | * @fb: fb to unregister | ||
527 | * | ||
528 | * Drivers need to call this when cleaning up driver-private framebuffers, e.g. | ||
529 | * those used for fbdev. Note that the caller must hold a reference of it's own, | ||
530 | * i.e. the object may not be destroyed through this call (since it'll lead to a | ||
531 | * locking inversion). | ||
532 | */ | ||
533 | void drm_framebuffer_unregister_private(struct drm_framebuffer *fb) | ||
534 | { | ||
535 | struct drm_device *dev; | ||
536 | |||
537 | if (!fb) | ||
538 | return; | ||
539 | |||
540 | dev = fb->dev; | ||
541 | |||
542 | /* Mark fb as reaped and drop idr ref. */ | ||
543 | drm_mode_object_unregister(dev, &fb->base); | ||
544 | } | ||
545 | EXPORT_SYMBOL(drm_framebuffer_unregister_private); | ||
546 | |||
547 | /** | ||
548 | * drm_framebuffer_cleanup - remove a framebuffer object | ||
549 | * @fb: framebuffer to remove | ||
550 | * | ||
551 | * Cleanup framebuffer. This function is intended to be used from the drivers | ||
552 | * ->destroy callback. It can also be used to clean up driver private | ||
553 | * framebuffers embedded into a larger structure. | ||
554 | * | ||
555 | * Note that this function does not remove the fb from active usuage - if it is | ||
556 | * still used anywhere, hilarity can ensue since userspace could call getfb on | ||
557 | * the id and get back -EINVAL. Obviously no concern at driver unload time. | ||
558 | * | ||
559 | * Also, the framebuffer will not be removed from the lookup idr - for | ||
560 | * user-created framebuffers this will happen in in the rmfb ioctl. For | ||
561 | * driver-private objects (e.g. for fbdev) drivers need to explicitly call | ||
562 | * drm_framebuffer_unregister_private. | ||
563 | */ | ||
564 | void drm_framebuffer_cleanup(struct drm_framebuffer *fb) | ||
565 | { | ||
566 | struct drm_device *dev = fb->dev; | ||
567 | |||
568 | mutex_lock(&dev->mode_config.fb_lock); | ||
569 | list_del(&fb->head); | ||
570 | dev->mode_config.num_fb--; | ||
571 | mutex_unlock(&dev->mode_config.fb_lock); | ||
572 | } | ||
573 | EXPORT_SYMBOL(drm_framebuffer_cleanup); | ||
574 | |||
575 | /** | ||
576 | * drm_framebuffer_remove - remove and unreference a framebuffer object | ||
577 | * @fb: framebuffer to remove | ||
578 | * | ||
579 | * Scans all the CRTCs and planes in @dev's mode_config. If they're | ||
580 | * using @fb, removes it, setting it to NULL. Then drops the reference to the | ||
581 | * passed-in framebuffer. Might take the modeset locks. | ||
582 | * | ||
583 | * Note that this function optimizes the cleanup away if the caller holds the | ||
584 | * last reference to the framebuffer. It is also guaranteed to not take the | ||
585 | * modeset locks in this case. | ||
586 | */ | ||
587 | void drm_framebuffer_remove(struct drm_framebuffer *fb) | ||
588 | { | ||
589 | struct drm_device *dev; | ||
590 | struct drm_crtc *crtc; | ||
591 | struct drm_plane *plane; | ||
592 | |||
593 | if (!fb) | ||
594 | return; | ||
595 | |||
596 | dev = fb->dev; | ||
597 | |||
598 | WARN_ON(!list_empty(&fb->filp_head)); | ||
599 | |||
600 | /* | ||
601 | * drm ABI mandates that we remove any deleted framebuffers from active | ||
602 | * useage. But since most sane clients only remove framebuffers they no | ||
603 | * longer need, try to optimize this away. | ||
604 | * | ||
605 | * Since we're holding a reference ourselves, observing a refcount of 1 | ||
606 | * means that we're the last holder and can skip it. Also, the refcount | ||
607 | * can never increase from 1 again, so we don't need any barriers or | ||
608 | * locks. | ||
609 | * | ||
610 | * Note that userspace could try to race with use and instate a new | ||
611 | * usage _after_ we've cleared all current ones. End result will be an | ||
612 | * in-use fb with fb-id == 0. Userspace is allowed to shoot its own foot | ||
613 | * in this manner. | ||
614 | */ | ||
615 | if (drm_framebuffer_read_refcount(fb) > 1) { | ||
616 | drm_modeset_lock_all(dev); | ||
617 | /* remove from any CRTC */ | ||
618 | drm_for_each_crtc(crtc, dev) { | ||
619 | if (crtc->primary->fb == fb) { | ||
620 | /* should turn off the crtc */ | ||
621 | if (drm_crtc_force_disable(crtc)) | ||
622 | DRM_ERROR("failed to reset crtc %p when fb was deleted\n", crtc); | ||
623 | } | ||
624 | } | ||
625 | |||
626 | drm_for_each_plane(plane, dev) { | ||
627 | if (plane->fb == fb) | ||
628 | drm_plane_force_disable(plane); | ||
629 | } | ||
630 | drm_modeset_unlock_all(dev); | ||
631 | } | ||
632 | |||
633 | drm_framebuffer_unreference(fb); | ||
634 | } | ||
635 | EXPORT_SYMBOL(drm_framebuffer_remove); | ||
636 | |||
637 | DEFINE_WW_CLASS(crtc_ww_class); | 273 | DEFINE_WW_CLASS(crtc_ww_class); |
638 | 274 | ||
639 | static unsigned int drm_num_crtcs(struct drm_device *dev) | 275 | static unsigned int drm_num_crtcs(struct drm_device *dev) |
@@ -783,360 +419,6 @@ void drm_crtc_cleanup(struct drm_crtc *crtc) | |||
783 | } | 419 | } |
784 | EXPORT_SYMBOL(drm_crtc_cleanup); | 420 | EXPORT_SYMBOL(drm_crtc_cleanup); |
785 | 421 | ||
786 | /* | ||
787 | * drm_mode_remove - remove and free a mode | ||
788 | * @connector: connector list to modify | ||
789 | * @mode: mode to remove | ||
790 | * | ||
791 | * Remove @mode from @connector's mode list, then free it. | ||
792 | */ | ||
793 | static void drm_mode_remove(struct drm_connector *connector, | ||
794 | struct drm_display_mode *mode) | ||
795 | { | ||
796 | list_del(&mode->head); | ||
797 | drm_mode_destroy(connector->dev, mode); | ||
798 | } | ||
799 | |||
800 | /** | ||
801 | * drm_display_info_set_bus_formats - set the supported bus formats | ||
802 | * @info: display info to store bus formats in | ||
803 | * @formats: array containing the supported bus formats | ||
804 | * @num_formats: the number of entries in the fmts array | ||
805 | * | ||
806 | * Store the supported bus formats in display info structure. | ||
807 | * See MEDIA_BUS_FMT_* definitions in include/uapi/linux/media-bus-format.h for | ||
808 | * a full list of available formats. | ||
809 | */ | ||
810 | int drm_display_info_set_bus_formats(struct drm_display_info *info, | ||
811 | const u32 *formats, | ||
812 | unsigned int num_formats) | ||
813 | { | ||
814 | u32 *fmts = NULL; | ||
815 | |||
816 | if (!formats && num_formats) | ||
817 | return -EINVAL; | ||
818 | |||
819 | if (formats && num_formats) { | ||
820 | fmts = kmemdup(formats, sizeof(*formats) * num_formats, | ||
821 | GFP_KERNEL); | ||
822 | if (!fmts) | ||
823 | return -ENOMEM; | ||
824 | } | ||
825 | |||
826 | kfree(info->bus_formats); | ||
827 | info->bus_formats = fmts; | ||
828 | info->num_bus_formats = num_formats; | ||
829 | |||
830 | return 0; | ||
831 | } | ||
832 | EXPORT_SYMBOL(drm_display_info_set_bus_formats); | ||
833 | |||
834 | /** | ||
835 | * drm_connector_get_cmdline_mode - reads the user's cmdline mode | ||
836 | * @connector: connector to quwery | ||
837 | * | ||
838 | * The kernel supports per-connector configration of its consoles through | ||
839 | * use of the video= parameter. This function parses that option and | ||
840 | * extracts the user's specified mode (or enable/disable status) for a | ||
841 | * particular connector. This is typically only used during the early fbdev | ||
842 | * setup. | ||
843 | */ | ||
844 | static void drm_connector_get_cmdline_mode(struct drm_connector *connector) | ||
845 | { | ||
846 | struct drm_cmdline_mode *mode = &connector->cmdline_mode; | ||
847 | char *option = NULL; | ||
848 | |||
849 | if (fb_get_options(connector->name, &option)) | ||
850 | return; | ||
851 | |||
852 | if (!drm_mode_parse_command_line_for_connector(option, | ||
853 | connector, | ||
854 | mode)) | ||
855 | return; | ||
856 | |||
857 | if (mode->force) { | ||
858 | const char *s; | ||
859 | |||
860 | switch (mode->force) { | ||
861 | case DRM_FORCE_OFF: | ||
862 | s = "OFF"; | ||
863 | break; | ||
864 | case DRM_FORCE_ON_DIGITAL: | ||
865 | s = "ON - dig"; | ||
866 | break; | ||
867 | default: | ||
868 | case DRM_FORCE_ON: | ||
869 | s = "ON"; | ||
870 | break; | ||
871 | } | ||
872 | |||
873 | DRM_INFO("forcing %s connector %s\n", connector->name, s); | ||
874 | connector->force = mode->force; | ||
875 | } | ||
876 | |||
877 | DRM_DEBUG_KMS("cmdline mode for connector %s %dx%d@%dHz%s%s%s\n", | ||
878 | connector->name, | ||
879 | mode->xres, mode->yres, | ||
880 | mode->refresh_specified ? mode->refresh : 60, | ||
881 | mode->rb ? " reduced blanking" : "", | ||
882 | mode->margins ? " with margins" : "", | ||
883 | mode->interlace ? " interlaced" : ""); | ||
884 | } | ||
885 | |||
886 | static void drm_connector_free(struct kref *kref) | ||
887 | { | ||
888 | struct drm_connector *connector = | ||
889 | container_of(kref, struct drm_connector, base.refcount); | ||
890 | struct drm_device *dev = connector->dev; | ||
891 | |||
892 | drm_mode_object_unregister(dev, &connector->base); | ||
893 | connector->funcs->destroy(connector); | ||
894 | } | ||
895 | |||
896 | /** | ||
897 | * drm_connector_init - Init a preallocated connector | ||
898 | * @dev: DRM device | ||
899 | * @connector: the connector to init | ||
900 | * @funcs: callbacks for this connector | ||
901 | * @connector_type: user visible type of the connector | ||
902 | * | ||
903 | * Initialises a preallocated connector. Connectors should be | ||
904 | * subclassed as part of driver connector objects. | ||
905 | * | ||
906 | * Returns: | ||
907 | * Zero on success, error code on failure. | ||
908 | */ | ||
909 | int drm_connector_init(struct drm_device *dev, | ||
910 | struct drm_connector *connector, | ||
911 | const struct drm_connector_funcs *funcs, | ||
912 | int connector_type) | ||
913 | { | ||
914 | struct drm_mode_config *config = &dev->mode_config; | ||
915 | int ret; | ||
916 | struct ida *connector_ida = | ||
917 | &drm_connector_enum_list[connector_type].ida; | ||
918 | |||
919 | drm_modeset_lock_all(dev); | ||
920 | |||
921 | ret = drm_mode_object_get_reg(dev, &connector->base, | ||
922 | DRM_MODE_OBJECT_CONNECTOR, | ||
923 | false, drm_connector_free); | ||
924 | if (ret) | ||
925 | goto out_unlock; | ||
926 | |||
927 | connector->base.properties = &connector->properties; | ||
928 | connector->dev = dev; | ||
929 | connector->funcs = funcs; | ||
930 | |||
931 | ret = ida_simple_get(&config->connector_ida, 0, 0, GFP_KERNEL); | ||
932 | if (ret < 0) | ||
933 | goto out_put; | ||
934 | connector->index = ret; | ||
935 | ret = 0; | ||
936 | |||
937 | connector->connector_type = connector_type; | ||
938 | connector->connector_type_id = | ||
939 | ida_simple_get(connector_ida, 1, 0, GFP_KERNEL); | ||
940 | if (connector->connector_type_id < 0) { | ||
941 | ret = connector->connector_type_id; | ||
942 | goto out_put_id; | ||
943 | } | ||
944 | connector->name = | ||
945 | kasprintf(GFP_KERNEL, "%s-%d", | ||
946 | drm_connector_enum_list[connector_type].name, | ||
947 | connector->connector_type_id); | ||
948 | if (!connector->name) { | ||
949 | ret = -ENOMEM; | ||
950 | goto out_put_type_id; | ||
951 | } | ||
952 | |||
953 | INIT_LIST_HEAD(&connector->probed_modes); | ||
954 | INIT_LIST_HEAD(&connector->modes); | ||
955 | connector->edid_blob_ptr = NULL; | ||
956 | connector->status = connector_status_unknown; | ||
957 | |||
958 | drm_connector_get_cmdline_mode(connector); | ||
959 | |||
960 | /* We should add connectors at the end to avoid upsetting the connector | ||
961 | * index too much. */ | ||
962 | list_add_tail(&connector->head, &config->connector_list); | ||
963 | config->num_connector++; | ||
964 | |||
965 | if (connector_type != DRM_MODE_CONNECTOR_VIRTUAL) | ||
966 | drm_object_attach_property(&connector->base, | ||
967 | config->edid_property, | ||
968 | 0); | ||
969 | |||
970 | drm_object_attach_property(&connector->base, | ||
971 | config->dpms_property, 0); | ||
972 | |||
973 | if (drm_core_check_feature(dev, DRIVER_ATOMIC)) { | ||
974 | drm_object_attach_property(&connector->base, config->prop_crtc_id, 0); | ||
975 | } | ||
976 | |||
977 | connector->debugfs_entry = NULL; | ||
978 | out_put_type_id: | ||
979 | if (ret) | ||
980 | ida_remove(connector_ida, connector->connector_type_id); | ||
981 | out_put_id: | ||
982 | if (ret) | ||
983 | ida_remove(&config->connector_ida, connector->index); | ||
984 | out_put: | ||
985 | if (ret) | ||
986 | drm_mode_object_unregister(dev, &connector->base); | ||
987 | |||
988 | out_unlock: | ||
989 | drm_modeset_unlock_all(dev); | ||
990 | |||
991 | return ret; | ||
992 | } | ||
993 | EXPORT_SYMBOL(drm_connector_init); | ||
994 | |||
995 | /** | ||
996 | * drm_connector_cleanup - cleans up an initialised connector | ||
997 | * @connector: connector to cleanup | ||
998 | * | ||
999 | * Cleans up the connector but doesn't free the object. | ||
1000 | */ | ||
1001 | void drm_connector_cleanup(struct drm_connector *connector) | ||
1002 | { | ||
1003 | struct drm_device *dev = connector->dev; | ||
1004 | struct drm_display_mode *mode, *t; | ||
1005 | |||
1006 | /* The connector should have been removed from userspace long before | ||
1007 | * it is finally destroyed. | ||
1008 | */ | ||
1009 | if (WARN_ON(connector->registered)) | ||
1010 | drm_connector_unregister(connector); | ||
1011 | |||
1012 | if (connector->tile_group) { | ||
1013 | drm_mode_put_tile_group(dev, connector->tile_group); | ||
1014 | connector->tile_group = NULL; | ||
1015 | } | ||
1016 | |||
1017 | list_for_each_entry_safe(mode, t, &connector->probed_modes, head) | ||
1018 | drm_mode_remove(connector, mode); | ||
1019 | |||
1020 | list_for_each_entry_safe(mode, t, &connector->modes, head) | ||
1021 | drm_mode_remove(connector, mode); | ||
1022 | |||
1023 | ida_remove(&drm_connector_enum_list[connector->connector_type].ida, | ||
1024 | connector->connector_type_id); | ||
1025 | |||
1026 | ida_remove(&dev->mode_config.connector_ida, | ||
1027 | connector->index); | ||
1028 | |||
1029 | kfree(connector->display_info.bus_formats); | ||
1030 | drm_mode_object_unregister(dev, &connector->base); | ||
1031 | kfree(connector->name); | ||
1032 | connector->name = NULL; | ||
1033 | list_del(&connector->head); | ||
1034 | dev->mode_config.num_connector--; | ||
1035 | |||
1036 | WARN_ON(connector->state && !connector->funcs->atomic_destroy_state); | ||
1037 | if (connector->state && connector->funcs->atomic_destroy_state) | ||
1038 | connector->funcs->atomic_destroy_state(connector, | ||
1039 | connector->state); | ||
1040 | |||
1041 | memset(connector, 0, sizeof(*connector)); | ||
1042 | } | ||
1043 | EXPORT_SYMBOL(drm_connector_cleanup); | ||
1044 | |||
1045 | /** | ||
1046 | * drm_connector_register - register a connector | ||
1047 | * @connector: the connector to register | ||
1048 | * | ||
1049 | * Register userspace interfaces for a connector | ||
1050 | * | ||
1051 | * Returns: | ||
1052 | * Zero on success, error code on failure. | ||
1053 | */ | ||
1054 | int drm_connector_register(struct drm_connector *connector) | ||
1055 | { | ||
1056 | int ret; | ||
1057 | |||
1058 | if (connector->registered) | ||
1059 | return 0; | ||
1060 | |||
1061 | ret = drm_sysfs_connector_add(connector); | ||
1062 | if (ret) | ||
1063 | return ret; | ||
1064 | |||
1065 | ret = drm_debugfs_connector_add(connector); | ||
1066 | if (ret) { | ||
1067 | goto err_sysfs; | ||
1068 | } | ||
1069 | |||
1070 | if (connector->funcs->late_register) { | ||
1071 | ret = connector->funcs->late_register(connector); | ||
1072 | if (ret) | ||
1073 | goto err_debugfs; | ||
1074 | } | ||
1075 | |||
1076 | drm_mode_object_register(connector->dev, &connector->base); | ||
1077 | |||
1078 | connector->registered = true; | ||
1079 | return 0; | ||
1080 | |||
1081 | err_debugfs: | ||
1082 | drm_debugfs_connector_remove(connector); | ||
1083 | err_sysfs: | ||
1084 | drm_sysfs_connector_remove(connector); | ||
1085 | return ret; | ||
1086 | } | ||
1087 | EXPORT_SYMBOL(drm_connector_register); | ||
1088 | |||
1089 | /** | ||
1090 | * drm_connector_unregister - unregister a connector | ||
1091 | * @connector: the connector to unregister | ||
1092 | * | ||
1093 | * Unregister userspace interfaces for a connector | ||
1094 | */ | ||
1095 | void drm_connector_unregister(struct drm_connector *connector) | ||
1096 | { | ||
1097 | if (!connector->registered) | ||
1098 | return; | ||
1099 | |||
1100 | if (connector->funcs->early_unregister) | ||
1101 | connector->funcs->early_unregister(connector); | ||
1102 | |||
1103 | drm_sysfs_connector_remove(connector); | ||
1104 | drm_debugfs_connector_remove(connector); | ||
1105 | |||
1106 | connector->registered = false; | ||
1107 | } | ||
1108 | EXPORT_SYMBOL(drm_connector_unregister); | ||
1109 | |||
1110 | static void drm_connector_unregister_all(struct drm_device *dev) | ||
1111 | { | ||
1112 | struct drm_connector *connector; | ||
1113 | |||
1114 | /* FIXME: taking the mode config mutex ends up in a clash with sysfs */ | ||
1115 | list_for_each_entry(connector, &dev->mode_config.connector_list, head) | ||
1116 | drm_connector_unregister(connector); | ||
1117 | } | ||
1118 | |||
1119 | static int drm_connector_register_all(struct drm_device *dev) | ||
1120 | { | ||
1121 | struct drm_connector *connector; | ||
1122 | int ret; | ||
1123 | |||
1124 | /* FIXME: taking the mode config mutex ends up in a clash with | ||
1125 | * fbcon/backlight registration */ | ||
1126 | list_for_each_entry(connector, &dev->mode_config.connector_list, head) { | ||
1127 | ret = drm_connector_register(connector); | ||
1128 | if (ret) | ||
1129 | goto err; | ||
1130 | } | ||
1131 | |||
1132 | return 0; | ||
1133 | |||
1134 | err: | ||
1135 | mutex_unlock(&dev->mode_config.mutex); | ||
1136 | drm_connector_unregister_all(dev); | ||
1137 | return ret; | ||
1138 | } | ||
1139 | |||
1140 | static int drm_encoder_register_all(struct drm_device *dev) | 422 | static int drm_encoder_register_all(struct drm_device *dev) |
1141 | { | 423 | { |
1142 | struct drm_encoder *encoder; | 424 | struct drm_encoder *encoder; |
@@ -1266,7 +548,7 @@ static unsigned int drm_num_planes(struct drm_device *dev) | |||
1266 | * @plane: plane object to init | 548 | * @plane: plane object to init |
1267 | * @possible_crtcs: bitmask of possible CRTCs | 549 | * @possible_crtcs: bitmask of possible CRTCs |
1268 | * @funcs: callbacks for the new plane | 550 | * @funcs: callbacks for the new plane |
1269 | * @formats: array of supported formats (%DRM_FORMAT_*) | 551 | * @formats: array of supported formats (DRM_FORMAT\_\*) |
1270 | * @format_count: number of elements in @formats | 552 | * @format_count: number of elements in @formats |
1271 | * @type: type of plane (overlay, primary, cursor) | 553 | * @type: type of plane (overlay, primary, cursor) |
1272 | * @name: printf style format string for the plane name, or NULL for default name | 554 | * @name: printf style format string for the plane name, or NULL for default name |
@@ -1381,7 +663,7 @@ static void drm_plane_unregister_all(struct drm_device *dev) | |||
1381 | * @plane: plane object to init | 663 | * @plane: plane object to init |
1382 | * @possible_crtcs: bitmask of possible CRTCs | 664 | * @possible_crtcs: bitmask of possible CRTCs |
1383 | * @funcs: callbacks for the new plane | 665 | * @funcs: callbacks for the new plane |
1384 | * @formats: array of supported formats (%DRM_FORMAT_*) | 666 | * @formats: array of supported formats (DRM_FORMAT\_\*) |
1385 | * @format_count: number of elements in @formats | 667 | * @format_count: number of elements in @formats |
1386 | * @is_primary: plane type (primary vs overlay) | 668 | * @is_primary: plane type (primary vs overlay) |
1387 | * | 669 | * |
@@ -1540,39 +822,11 @@ void drm_modeset_unregister_all(struct drm_device *dev) | |||
1540 | static int drm_mode_create_standard_properties(struct drm_device *dev) | 822 | static int drm_mode_create_standard_properties(struct drm_device *dev) |
1541 | { | 823 | { |
1542 | struct drm_property *prop; | 824 | struct drm_property *prop; |
825 | int ret; | ||
1543 | 826 | ||
1544 | /* | 827 | ret = drm_connector_create_standard_properties(dev); |
1545 | * Standard properties (apply to all connectors) | 828 | if (ret) |
1546 | */ | 829 | return ret; |
1547 | prop = drm_property_create(dev, DRM_MODE_PROP_BLOB | | ||
1548 | DRM_MODE_PROP_IMMUTABLE, | ||
1549 | "EDID", 0); | ||
1550 | if (!prop) | ||
1551 | return -ENOMEM; | ||
1552 | dev->mode_config.edid_property = prop; | ||
1553 | |||
1554 | prop = drm_property_create_enum(dev, 0, | ||
1555 | "DPMS", drm_dpms_enum_list, | ||
1556 | ARRAY_SIZE(drm_dpms_enum_list)); | ||
1557 | if (!prop) | ||
1558 | return -ENOMEM; | ||
1559 | dev->mode_config.dpms_property = prop; | ||
1560 | |||
1561 | prop = drm_property_create(dev, | ||
1562 | DRM_MODE_PROP_BLOB | | ||
1563 | DRM_MODE_PROP_IMMUTABLE, | ||
1564 | "PATH", 0); | ||
1565 | if (!prop) | ||
1566 | return -ENOMEM; | ||
1567 | dev->mode_config.path_property = prop; | ||
1568 | |||
1569 | prop = drm_property_create(dev, | ||
1570 | DRM_MODE_PROP_BLOB | | ||
1571 | DRM_MODE_PROP_IMMUTABLE, | ||
1572 | "TILE", 0); | ||
1573 | if (!prop) | ||
1574 | return -ENOMEM; | ||
1575 | dev->mode_config.tile_property = prop; | ||
1576 | 830 | ||
1577 | prop = drm_property_create_enum(dev, DRM_MODE_PROP_IMMUTABLE, | 831 | prop = drm_property_create_enum(dev, DRM_MODE_PROP_IMMUTABLE, |
1578 | "type", drm_plane_type_enum_list, | 832 | "type", drm_plane_type_enum_list, |
@@ -1693,250 +947,6 @@ static int drm_mode_create_standard_properties(struct drm_device *dev) | |||
1693 | } | 947 | } |
1694 | 948 | ||
1695 | /** | 949 | /** |
1696 | * drm_mode_create_dvi_i_properties - create DVI-I specific connector properties | ||
1697 | * @dev: DRM device | ||
1698 | * | ||
1699 | * Called by a driver the first time a DVI-I connector is made. | ||
1700 | */ | ||
1701 | int drm_mode_create_dvi_i_properties(struct drm_device *dev) | ||
1702 | { | ||
1703 | struct drm_property *dvi_i_selector; | ||
1704 | struct drm_property *dvi_i_subconnector; | ||
1705 | |||
1706 | if (dev->mode_config.dvi_i_select_subconnector_property) | ||
1707 | return 0; | ||
1708 | |||
1709 | dvi_i_selector = | ||
1710 | drm_property_create_enum(dev, 0, | ||
1711 | "select subconnector", | ||
1712 | drm_dvi_i_select_enum_list, | ||
1713 | ARRAY_SIZE(drm_dvi_i_select_enum_list)); | ||
1714 | dev->mode_config.dvi_i_select_subconnector_property = dvi_i_selector; | ||
1715 | |||
1716 | dvi_i_subconnector = drm_property_create_enum(dev, DRM_MODE_PROP_IMMUTABLE, | ||
1717 | "subconnector", | ||
1718 | drm_dvi_i_subconnector_enum_list, | ||
1719 | ARRAY_SIZE(drm_dvi_i_subconnector_enum_list)); | ||
1720 | dev->mode_config.dvi_i_subconnector_property = dvi_i_subconnector; | ||
1721 | |||
1722 | return 0; | ||
1723 | } | ||
1724 | EXPORT_SYMBOL(drm_mode_create_dvi_i_properties); | ||
1725 | |||
1726 | /** | ||
1727 | * drm_create_tv_properties - create TV specific connector properties | ||
1728 | * @dev: DRM device | ||
1729 | * @num_modes: number of different TV formats (modes) supported | ||
1730 | * @modes: array of pointers to strings containing name of each format | ||
1731 | * | ||
1732 | * Called by a driver's TV initialization routine, this function creates | ||
1733 | * the TV specific connector properties for a given device. Caller is | ||
1734 | * responsible for allocating a list of format names and passing them to | ||
1735 | * this routine. | ||
1736 | */ | ||
1737 | int drm_mode_create_tv_properties(struct drm_device *dev, | ||
1738 | unsigned int num_modes, | ||
1739 | const char * const modes[]) | ||
1740 | { | ||
1741 | struct drm_property *tv_selector; | ||
1742 | struct drm_property *tv_subconnector; | ||
1743 | unsigned int i; | ||
1744 | |||
1745 | if (dev->mode_config.tv_select_subconnector_property) | ||
1746 | return 0; | ||
1747 | |||
1748 | /* | ||
1749 | * Basic connector properties | ||
1750 | */ | ||
1751 | tv_selector = drm_property_create_enum(dev, 0, | ||
1752 | "select subconnector", | ||
1753 | drm_tv_select_enum_list, | ||
1754 | ARRAY_SIZE(drm_tv_select_enum_list)); | ||
1755 | if (!tv_selector) | ||
1756 | goto nomem; | ||
1757 | |||
1758 | dev->mode_config.tv_select_subconnector_property = tv_selector; | ||
1759 | |||
1760 | tv_subconnector = | ||
1761 | drm_property_create_enum(dev, DRM_MODE_PROP_IMMUTABLE, | ||
1762 | "subconnector", | ||
1763 | drm_tv_subconnector_enum_list, | ||
1764 | ARRAY_SIZE(drm_tv_subconnector_enum_list)); | ||
1765 | if (!tv_subconnector) | ||
1766 | goto nomem; | ||
1767 | dev->mode_config.tv_subconnector_property = tv_subconnector; | ||
1768 | |||
1769 | /* | ||
1770 | * Other, TV specific properties: margins & TV modes. | ||
1771 | */ | ||
1772 | dev->mode_config.tv_left_margin_property = | ||
1773 | drm_property_create_range(dev, 0, "left margin", 0, 100); | ||
1774 | if (!dev->mode_config.tv_left_margin_property) | ||
1775 | goto nomem; | ||
1776 | |||
1777 | dev->mode_config.tv_right_margin_property = | ||
1778 | drm_property_create_range(dev, 0, "right margin", 0, 100); | ||
1779 | if (!dev->mode_config.tv_right_margin_property) | ||
1780 | goto nomem; | ||
1781 | |||
1782 | dev->mode_config.tv_top_margin_property = | ||
1783 | drm_property_create_range(dev, 0, "top margin", 0, 100); | ||
1784 | if (!dev->mode_config.tv_top_margin_property) | ||
1785 | goto nomem; | ||
1786 | |||
1787 | dev->mode_config.tv_bottom_margin_property = | ||
1788 | drm_property_create_range(dev, 0, "bottom margin", 0, 100); | ||
1789 | if (!dev->mode_config.tv_bottom_margin_property) | ||
1790 | goto nomem; | ||
1791 | |||
1792 | dev->mode_config.tv_mode_property = | ||
1793 | drm_property_create(dev, DRM_MODE_PROP_ENUM, | ||
1794 | "mode", num_modes); | ||
1795 | if (!dev->mode_config.tv_mode_property) | ||
1796 | goto nomem; | ||
1797 | |||
1798 | for (i = 0; i < num_modes; i++) | ||
1799 | drm_property_add_enum(dev->mode_config.tv_mode_property, i, | ||
1800 | i, modes[i]); | ||
1801 | |||
1802 | dev->mode_config.tv_brightness_property = | ||
1803 | drm_property_create_range(dev, 0, "brightness", 0, 100); | ||
1804 | if (!dev->mode_config.tv_brightness_property) | ||
1805 | goto nomem; | ||
1806 | |||
1807 | dev->mode_config.tv_contrast_property = | ||
1808 | drm_property_create_range(dev, 0, "contrast", 0, 100); | ||
1809 | if (!dev->mode_config.tv_contrast_property) | ||
1810 | goto nomem; | ||
1811 | |||
1812 | dev->mode_config.tv_flicker_reduction_property = | ||
1813 | drm_property_create_range(dev, 0, "flicker reduction", 0, 100); | ||
1814 | if (!dev->mode_config.tv_flicker_reduction_property) | ||
1815 | goto nomem; | ||
1816 | |||
1817 | dev->mode_config.tv_overscan_property = | ||
1818 | drm_property_create_range(dev, 0, "overscan", 0, 100); | ||
1819 | if (!dev->mode_config.tv_overscan_property) | ||
1820 | goto nomem; | ||
1821 | |||
1822 | dev->mode_config.tv_saturation_property = | ||
1823 | drm_property_create_range(dev, 0, "saturation", 0, 100); | ||
1824 | if (!dev->mode_config.tv_saturation_property) | ||
1825 | goto nomem; | ||
1826 | |||
1827 | dev->mode_config.tv_hue_property = | ||
1828 | drm_property_create_range(dev, 0, "hue", 0, 100); | ||
1829 | if (!dev->mode_config.tv_hue_property) | ||
1830 | goto nomem; | ||
1831 | |||
1832 | return 0; | ||
1833 | nomem: | ||
1834 | return -ENOMEM; | ||
1835 | } | ||
1836 | EXPORT_SYMBOL(drm_mode_create_tv_properties); | ||
1837 | |||
1838 | /** | ||
1839 | * drm_mode_create_scaling_mode_property - create scaling mode property | ||
1840 | * @dev: DRM device | ||
1841 | * | ||
1842 | * Called by a driver the first time it's needed, must be attached to desired | ||
1843 | * connectors. | ||
1844 | */ | ||
1845 | int drm_mode_create_scaling_mode_property(struct drm_device *dev) | ||
1846 | { | ||
1847 | struct drm_property *scaling_mode; | ||
1848 | |||
1849 | if (dev->mode_config.scaling_mode_property) | ||
1850 | return 0; | ||
1851 | |||
1852 | scaling_mode = | ||
1853 | drm_property_create_enum(dev, 0, "scaling mode", | ||
1854 | drm_scaling_mode_enum_list, | ||
1855 | ARRAY_SIZE(drm_scaling_mode_enum_list)); | ||
1856 | |||
1857 | dev->mode_config.scaling_mode_property = scaling_mode; | ||
1858 | |||
1859 | return 0; | ||
1860 | } | ||
1861 | EXPORT_SYMBOL(drm_mode_create_scaling_mode_property); | ||
1862 | |||
1863 | /** | ||
1864 | * drm_mode_create_aspect_ratio_property - create aspect ratio property | ||
1865 | * @dev: DRM device | ||
1866 | * | ||
1867 | * Called by a driver the first time it's needed, must be attached to desired | ||
1868 | * connectors. | ||
1869 | * | ||
1870 | * Returns: | ||
1871 | * Zero on success, negative errno on failure. | ||
1872 | */ | ||
1873 | int drm_mode_create_aspect_ratio_property(struct drm_device *dev) | ||
1874 | { | ||
1875 | if (dev->mode_config.aspect_ratio_property) | ||
1876 | return 0; | ||
1877 | |||
1878 | dev->mode_config.aspect_ratio_property = | ||
1879 | drm_property_create_enum(dev, 0, "aspect ratio", | ||
1880 | drm_aspect_ratio_enum_list, | ||
1881 | ARRAY_SIZE(drm_aspect_ratio_enum_list)); | ||
1882 | |||
1883 | if (dev->mode_config.aspect_ratio_property == NULL) | ||
1884 | return -ENOMEM; | ||
1885 | |||
1886 | return 0; | ||
1887 | } | ||
1888 | EXPORT_SYMBOL(drm_mode_create_aspect_ratio_property); | ||
1889 | |||
1890 | /** | ||
1891 | * drm_mode_create_dirty_property - create dirty property | ||
1892 | * @dev: DRM device | ||
1893 | * | ||
1894 | * Called by a driver the first time it's needed, must be attached to desired | ||
1895 | * connectors. | ||
1896 | */ | ||
1897 | int drm_mode_create_dirty_info_property(struct drm_device *dev) | ||
1898 | { | ||
1899 | struct drm_property *dirty_info; | ||
1900 | |||
1901 | if (dev->mode_config.dirty_info_property) | ||
1902 | return 0; | ||
1903 | |||
1904 | dirty_info = | ||
1905 | drm_property_create_enum(dev, DRM_MODE_PROP_IMMUTABLE, | ||
1906 | "dirty", | ||
1907 | drm_dirty_info_enum_list, | ||
1908 | ARRAY_SIZE(drm_dirty_info_enum_list)); | ||
1909 | dev->mode_config.dirty_info_property = dirty_info; | ||
1910 | |||
1911 | return 0; | ||
1912 | } | ||
1913 | EXPORT_SYMBOL(drm_mode_create_dirty_info_property); | ||
1914 | |||
1915 | /** | ||
1916 | * drm_mode_create_suggested_offset_properties - create suggests offset properties | ||
1917 | * @dev: DRM device | ||
1918 | * | ||
1919 | * Create the the suggested x/y offset property for connectors. | ||
1920 | */ | ||
1921 | int drm_mode_create_suggested_offset_properties(struct drm_device *dev) | ||
1922 | { | ||
1923 | if (dev->mode_config.suggested_x_property && dev->mode_config.suggested_y_property) | ||
1924 | return 0; | ||
1925 | |||
1926 | dev->mode_config.suggested_x_property = | ||
1927 | drm_property_create_range(dev, DRM_MODE_PROP_IMMUTABLE, "suggested X", 0, 0xffffffff); | ||
1928 | |||
1929 | dev->mode_config.suggested_y_property = | ||
1930 | drm_property_create_range(dev, DRM_MODE_PROP_IMMUTABLE, "suggested Y", 0, 0xffffffff); | ||
1931 | |||
1932 | if (dev->mode_config.suggested_x_property == NULL || | ||
1933 | dev->mode_config.suggested_y_property == NULL) | ||
1934 | return -ENOMEM; | ||
1935 | return 0; | ||
1936 | } | ||
1937 | EXPORT_SYMBOL(drm_mode_create_suggested_offset_properties); | ||
1938 | |||
1939 | /** | ||
1940 | * drm_mode_getresources - get graphics configuration | 950 | * drm_mode_getresources - get graphics configuration |
1941 | * @dev: drm device for the ioctl | 951 | * @dev: drm device for the ioctl |
1942 | * @data: data pointer for the ioctl | 952 | * @data: data pointer for the ioctl |
@@ -2123,32 +1133,11 @@ int drm_mode_getcrtc(struct drm_device *dev, | |||
2123 | return 0; | 1133 | return 0; |
2124 | } | 1134 | } |
2125 | 1135 | ||
2126 | static bool drm_mode_expose_to_userspace(const struct drm_display_mode *mode, | ||
2127 | const struct drm_file *file_priv) | ||
2128 | { | ||
2129 | /* | ||
2130 | * If user-space hasn't configured the driver to expose the stereo 3D | ||
2131 | * modes, don't expose them. | ||
2132 | */ | ||
2133 | if (!file_priv->stereo_allowed && drm_mode_is_stereo(mode)) | ||
2134 | return false; | ||
2135 | |||
2136 | return true; | ||
2137 | } | ||
2138 | |||
2139 | static struct drm_encoder *drm_connector_get_encoder(struct drm_connector *connector) | ||
2140 | { | ||
2141 | /* For atomic drivers only state objects are synchronously updated and | ||
2142 | * protected by modeset locks, so check those first. */ | ||
2143 | if (connector->state) | ||
2144 | return connector->state->best_encoder; | ||
2145 | return connector->encoder; | ||
2146 | } | ||
2147 | |||
2148 | /* helper for getconnector and getproperties ioctls */ | 1136 | /* helper for getconnector and getproperties ioctls */ |
2149 | static int get_properties(struct drm_mode_object *obj, bool atomic, | 1137 | int drm_mode_object_get_properties(struct drm_mode_object *obj, bool atomic, |
2150 | uint32_t __user *prop_ptr, uint64_t __user *prop_values, | 1138 | uint32_t __user *prop_ptr, |
2151 | uint32_t *arg_count_props) | 1139 | uint64_t __user *prop_values, |
1140 | uint32_t *arg_count_props) | ||
2152 | { | 1141 | { |
2153 | int props_count; | 1142 | int props_count; |
2154 | int i, ret, copied; | 1143 | int i, ret, copied; |
@@ -2183,133 +1172,6 @@ static int get_properties(struct drm_mode_object *obj, bool atomic, | |||
2183 | return 0; | 1172 | return 0; |
2184 | } | 1173 | } |
2185 | 1174 | ||
2186 | /** | ||
2187 | * drm_mode_getconnector - get connector configuration | ||
2188 | * @dev: drm device for the ioctl | ||
2189 | * @data: data pointer for the ioctl | ||
2190 | * @file_priv: drm file for the ioctl call | ||
2191 | * | ||
2192 | * Construct a connector configuration structure to return to the user. | ||
2193 | * | ||
2194 | * Called by the user via ioctl. | ||
2195 | * | ||
2196 | * Returns: | ||
2197 | * Zero on success, negative errno on failure. | ||
2198 | */ | ||
2199 | int drm_mode_getconnector(struct drm_device *dev, void *data, | ||
2200 | struct drm_file *file_priv) | ||
2201 | { | ||
2202 | struct drm_mode_get_connector *out_resp = data; | ||
2203 | struct drm_connector *connector; | ||
2204 | struct drm_encoder *encoder; | ||
2205 | struct drm_display_mode *mode; | ||
2206 | int mode_count = 0; | ||
2207 | int encoders_count = 0; | ||
2208 | int ret = 0; | ||
2209 | int copied = 0; | ||
2210 | int i; | ||
2211 | struct drm_mode_modeinfo u_mode; | ||
2212 | struct drm_mode_modeinfo __user *mode_ptr; | ||
2213 | uint32_t __user *encoder_ptr; | ||
2214 | |||
2215 | if (!drm_core_check_feature(dev, DRIVER_MODESET)) | ||
2216 | return -EINVAL; | ||
2217 | |||
2218 | memset(&u_mode, 0, sizeof(struct drm_mode_modeinfo)); | ||
2219 | |||
2220 | mutex_lock(&dev->mode_config.mutex); | ||
2221 | |||
2222 | connector = drm_connector_lookup(dev, out_resp->connector_id); | ||
2223 | if (!connector) { | ||
2224 | ret = -ENOENT; | ||
2225 | goto out_unlock; | ||
2226 | } | ||
2227 | |||
2228 | for (i = 0; i < DRM_CONNECTOR_MAX_ENCODER; i++) | ||
2229 | if (connector->encoder_ids[i] != 0) | ||
2230 | encoders_count++; | ||
2231 | |||
2232 | if (out_resp->count_modes == 0) { | ||
2233 | connector->funcs->fill_modes(connector, | ||
2234 | dev->mode_config.max_width, | ||
2235 | dev->mode_config.max_height); | ||
2236 | } | ||
2237 | |||
2238 | /* delayed so we get modes regardless of pre-fill_modes state */ | ||
2239 | list_for_each_entry(mode, &connector->modes, head) | ||
2240 | if (drm_mode_expose_to_userspace(mode, file_priv)) | ||
2241 | mode_count++; | ||
2242 | |||
2243 | out_resp->connector_id = connector->base.id; | ||
2244 | out_resp->connector_type = connector->connector_type; | ||
2245 | out_resp->connector_type_id = connector->connector_type_id; | ||
2246 | out_resp->mm_width = connector->display_info.width_mm; | ||
2247 | out_resp->mm_height = connector->display_info.height_mm; | ||
2248 | out_resp->subpixel = connector->display_info.subpixel_order; | ||
2249 | out_resp->connection = connector->status; | ||
2250 | |||
2251 | drm_modeset_lock(&dev->mode_config.connection_mutex, NULL); | ||
2252 | encoder = drm_connector_get_encoder(connector); | ||
2253 | if (encoder) | ||
2254 | out_resp->encoder_id = encoder->base.id; | ||
2255 | else | ||
2256 | out_resp->encoder_id = 0; | ||
2257 | |||
2258 | /* | ||
2259 | * This ioctl is called twice, once to determine how much space is | ||
2260 | * needed, and the 2nd time to fill it. | ||
2261 | */ | ||
2262 | if ((out_resp->count_modes >= mode_count) && mode_count) { | ||
2263 | copied = 0; | ||
2264 | mode_ptr = (struct drm_mode_modeinfo __user *)(unsigned long)out_resp->modes_ptr; | ||
2265 | list_for_each_entry(mode, &connector->modes, head) { | ||
2266 | if (!drm_mode_expose_to_userspace(mode, file_priv)) | ||
2267 | continue; | ||
2268 | |||
2269 | drm_mode_convert_to_umode(&u_mode, mode); | ||
2270 | if (copy_to_user(mode_ptr + copied, | ||
2271 | &u_mode, sizeof(u_mode))) { | ||
2272 | ret = -EFAULT; | ||
2273 | goto out; | ||
2274 | } | ||
2275 | copied++; | ||
2276 | } | ||
2277 | } | ||
2278 | out_resp->count_modes = mode_count; | ||
2279 | |||
2280 | ret = get_properties(&connector->base, file_priv->atomic, | ||
2281 | (uint32_t __user *)(unsigned long)(out_resp->props_ptr), | ||
2282 | (uint64_t __user *)(unsigned long)(out_resp->prop_values_ptr), | ||
2283 | &out_resp->count_props); | ||
2284 | if (ret) | ||
2285 | goto out; | ||
2286 | |||
2287 | if ((out_resp->count_encoders >= encoders_count) && encoders_count) { | ||
2288 | copied = 0; | ||
2289 | encoder_ptr = (uint32_t __user *)(unsigned long)(out_resp->encoders_ptr); | ||
2290 | for (i = 0; i < DRM_CONNECTOR_MAX_ENCODER; i++) { | ||
2291 | if (connector->encoder_ids[i] != 0) { | ||
2292 | if (put_user(connector->encoder_ids[i], | ||
2293 | encoder_ptr + copied)) { | ||
2294 | ret = -EFAULT; | ||
2295 | goto out; | ||
2296 | } | ||
2297 | copied++; | ||
2298 | } | ||
2299 | } | ||
2300 | } | ||
2301 | out_resp->count_encoders = encoders_count; | ||
2302 | |||
2303 | out: | ||
2304 | drm_modeset_unlock(&dev->mode_config.connection_mutex); | ||
2305 | |||
2306 | drm_connector_unreference(connector); | ||
2307 | out_unlock: | ||
2308 | mutex_unlock(&dev->mode_config.mutex); | ||
2309 | |||
2310 | return ret; | ||
2311 | } | ||
2312 | |||
2313 | static struct drm_crtc *drm_encoder_get_crtc(struct drm_encoder *encoder) | 1175 | static struct drm_crtc *drm_encoder_get_crtc(struct drm_encoder *encoder) |
2314 | { | 1176 | { |
2315 | struct drm_connector *connector; | 1177 | struct drm_connector *connector; |
@@ -2592,8 +1454,9 @@ static int __setplane_internal(struct drm_plane *plane, | |||
2592 | /* Check whether this plane supports the fb pixel format. */ | 1454 | /* Check whether this plane supports the fb pixel format. */ |
2593 | ret = drm_plane_check_pixel_format(plane, fb->pixel_format); | 1455 | ret = drm_plane_check_pixel_format(plane, fb->pixel_format); |
2594 | if (ret) { | 1456 | if (ret) { |
2595 | DRM_DEBUG_KMS("Invalid pixel format %s\n", | 1457 | char *format_name = drm_get_format_name(fb->pixel_format); |
2596 | drm_get_format_name(fb->pixel_format)); | 1458 | DRM_DEBUG_KMS("Invalid pixel format %s\n", format_name); |
1459 | kfree(format_name); | ||
2597 | goto out; | 1460 | goto out; |
2598 | } | 1461 | } |
2599 | 1462 | ||
@@ -2902,8 +1765,9 @@ int drm_mode_setcrtc(struct drm_device *dev, void *data, | |||
2902 | ret = drm_plane_check_pixel_format(crtc->primary, | 1765 | ret = drm_plane_check_pixel_format(crtc->primary, |
2903 | fb->pixel_format); | 1766 | fb->pixel_format); |
2904 | if (ret) { | 1767 | if (ret) { |
2905 | DRM_DEBUG_KMS("Invalid pixel format %s\n", | 1768 | char *format_name = drm_get_format_name(fb->pixel_format); |
2906 | drm_get_format_name(fb->pixel_format)); | 1769 | DRM_DEBUG_KMS("Invalid pixel format %s\n", format_name); |
1770 | kfree(format_name); | ||
2907 | goto out; | 1771 | goto out; |
2908 | } | 1772 | } |
2909 | } | 1773 | } |
@@ -3040,7 +1904,7 @@ static int drm_mode_cursor_universal(struct drm_crtc *crtc, | |||
3040 | */ | 1904 | */ |
3041 | if (req->flags & DRM_MODE_CURSOR_BO) { | 1905 | if (req->flags & DRM_MODE_CURSOR_BO) { |
3042 | if (req->handle) { | 1906 | if (req->handle) { |
3043 | fb = internal_framebuffer_create(dev, &fbreq, file_priv); | 1907 | fb = drm_internal_framebuffer_create(dev, &fbreq, file_priv); |
3044 | if (IS_ERR(fb)) { | 1908 | if (IS_ERR(fb)) { |
3045 | DRM_DEBUG_KMS("failed to wrap cursor buffer in drm framebuffer\n"); | 1909 | DRM_DEBUG_KMS("failed to wrap cursor buffer in drm framebuffer\n"); |
3046 | return PTR_ERR(fb); | 1910 | return PTR_ERR(fb); |
@@ -3238,578 +2102,6 @@ uint32_t drm_mode_legacy_fb_format(uint32_t bpp, uint32_t depth) | |||
3238 | } | 2102 | } |
3239 | EXPORT_SYMBOL(drm_mode_legacy_fb_format); | 2103 | EXPORT_SYMBOL(drm_mode_legacy_fb_format); |
3240 | 2104 | ||
3241 | /** | ||
3242 | * drm_mode_addfb - add an FB to the graphics configuration | ||
3243 | * @dev: drm device for the ioctl | ||
3244 | * @data: data pointer for the ioctl | ||
3245 | * @file_priv: drm file for the ioctl call | ||
3246 | * | ||
3247 | * Add a new FB to the specified CRTC, given a user request. This is the | ||
3248 | * original addfb ioctl which only supported RGB formats. | ||
3249 | * | ||
3250 | * Called by the user via ioctl. | ||
3251 | * | ||
3252 | * Returns: | ||
3253 | * Zero on success, negative errno on failure. | ||
3254 | */ | ||
3255 | int drm_mode_addfb(struct drm_device *dev, | ||
3256 | void *data, struct drm_file *file_priv) | ||
3257 | { | ||
3258 | struct drm_mode_fb_cmd *or = data; | ||
3259 | struct drm_mode_fb_cmd2 r = {}; | ||
3260 | int ret; | ||
3261 | |||
3262 | /* convert to new format and call new ioctl */ | ||
3263 | r.fb_id = or->fb_id; | ||
3264 | r.width = or->width; | ||
3265 | r.height = or->height; | ||
3266 | r.pitches[0] = or->pitch; | ||
3267 | r.pixel_format = drm_mode_legacy_fb_format(or->bpp, or->depth); | ||
3268 | r.handles[0] = or->handle; | ||
3269 | |||
3270 | ret = drm_mode_addfb2(dev, &r, file_priv); | ||
3271 | if (ret) | ||
3272 | return ret; | ||
3273 | |||
3274 | or->fb_id = r.fb_id; | ||
3275 | |||
3276 | return 0; | ||
3277 | } | ||
3278 | |||
3279 | static int format_check(const struct drm_mode_fb_cmd2 *r) | ||
3280 | { | ||
3281 | uint32_t format = r->pixel_format & ~DRM_FORMAT_BIG_ENDIAN; | ||
3282 | |||
3283 | switch (format) { | ||
3284 | case DRM_FORMAT_C8: | ||
3285 | case DRM_FORMAT_RGB332: | ||
3286 | case DRM_FORMAT_BGR233: | ||
3287 | case DRM_FORMAT_XRGB4444: | ||
3288 | case DRM_FORMAT_XBGR4444: | ||
3289 | case DRM_FORMAT_RGBX4444: | ||
3290 | case DRM_FORMAT_BGRX4444: | ||
3291 | case DRM_FORMAT_ARGB4444: | ||
3292 | case DRM_FORMAT_ABGR4444: | ||
3293 | case DRM_FORMAT_RGBA4444: | ||
3294 | case DRM_FORMAT_BGRA4444: | ||
3295 | case DRM_FORMAT_XRGB1555: | ||
3296 | case DRM_FORMAT_XBGR1555: | ||
3297 | case DRM_FORMAT_RGBX5551: | ||
3298 | case DRM_FORMAT_BGRX5551: | ||
3299 | case DRM_FORMAT_ARGB1555: | ||
3300 | case DRM_FORMAT_ABGR1555: | ||
3301 | case DRM_FORMAT_RGBA5551: | ||
3302 | case DRM_FORMAT_BGRA5551: | ||
3303 | case DRM_FORMAT_RGB565: | ||
3304 | case DRM_FORMAT_BGR565: | ||
3305 | case DRM_FORMAT_RGB888: | ||
3306 | case DRM_FORMAT_BGR888: | ||
3307 | case DRM_FORMAT_XRGB8888: | ||
3308 | case DRM_FORMAT_XBGR8888: | ||
3309 | case DRM_FORMAT_RGBX8888: | ||
3310 | case DRM_FORMAT_BGRX8888: | ||
3311 | case DRM_FORMAT_ARGB8888: | ||
3312 | case DRM_FORMAT_ABGR8888: | ||
3313 | case DRM_FORMAT_RGBA8888: | ||
3314 | case DRM_FORMAT_BGRA8888: | ||
3315 | case DRM_FORMAT_XRGB2101010: | ||
3316 | case DRM_FORMAT_XBGR2101010: | ||
3317 | case DRM_FORMAT_RGBX1010102: | ||
3318 | case DRM_FORMAT_BGRX1010102: | ||
3319 | case DRM_FORMAT_ARGB2101010: | ||
3320 | case DRM_FORMAT_ABGR2101010: | ||
3321 | case DRM_FORMAT_RGBA1010102: | ||
3322 | case DRM_FORMAT_BGRA1010102: | ||
3323 | case DRM_FORMAT_YUYV: | ||
3324 | case DRM_FORMAT_YVYU: | ||
3325 | case DRM_FORMAT_UYVY: | ||
3326 | case DRM_FORMAT_VYUY: | ||
3327 | case DRM_FORMAT_AYUV: | ||
3328 | case DRM_FORMAT_NV12: | ||
3329 | case DRM_FORMAT_NV21: | ||
3330 | case DRM_FORMAT_NV16: | ||
3331 | case DRM_FORMAT_NV61: | ||
3332 | case DRM_FORMAT_NV24: | ||
3333 | case DRM_FORMAT_NV42: | ||
3334 | case DRM_FORMAT_YUV410: | ||
3335 | case DRM_FORMAT_YVU410: | ||
3336 | case DRM_FORMAT_YUV411: | ||
3337 | case DRM_FORMAT_YVU411: | ||
3338 | case DRM_FORMAT_YUV420: | ||
3339 | case DRM_FORMAT_YVU420: | ||
3340 | case DRM_FORMAT_YUV422: | ||
3341 | case DRM_FORMAT_YVU422: | ||
3342 | case DRM_FORMAT_YUV444: | ||
3343 | case DRM_FORMAT_YVU444: | ||
3344 | return 0; | ||
3345 | default: | ||
3346 | DRM_DEBUG_KMS("invalid pixel format %s\n", | ||
3347 | drm_get_format_name(r->pixel_format)); | ||
3348 | return -EINVAL; | ||
3349 | } | ||
3350 | } | ||
3351 | |||
3352 | static int framebuffer_check(const struct drm_mode_fb_cmd2 *r) | ||
3353 | { | ||
3354 | int ret, hsub, vsub, num_planes, i; | ||
3355 | |||
3356 | ret = format_check(r); | ||
3357 | if (ret) { | ||
3358 | DRM_DEBUG_KMS("bad framebuffer format %s\n", | ||
3359 | drm_get_format_name(r->pixel_format)); | ||
3360 | return ret; | ||
3361 | } | ||
3362 | |||
3363 | hsub = drm_format_horz_chroma_subsampling(r->pixel_format); | ||
3364 | vsub = drm_format_vert_chroma_subsampling(r->pixel_format); | ||
3365 | num_planes = drm_format_num_planes(r->pixel_format); | ||
3366 | |||
3367 | if (r->width == 0 || r->width % hsub) { | ||
3368 | DRM_DEBUG_KMS("bad framebuffer width %u\n", r->width); | ||
3369 | return -EINVAL; | ||
3370 | } | ||
3371 | |||
3372 | if (r->height == 0 || r->height % vsub) { | ||
3373 | DRM_DEBUG_KMS("bad framebuffer height %u\n", r->height); | ||
3374 | return -EINVAL; | ||
3375 | } | ||
3376 | |||
3377 | for (i = 0; i < num_planes; i++) { | ||
3378 | unsigned int width = r->width / (i != 0 ? hsub : 1); | ||
3379 | unsigned int height = r->height / (i != 0 ? vsub : 1); | ||
3380 | unsigned int cpp = drm_format_plane_cpp(r->pixel_format, i); | ||
3381 | |||
3382 | if (!r->handles[i]) { | ||
3383 | DRM_DEBUG_KMS("no buffer object handle for plane %d\n", i); | ||
3384 | return -EINVAL; | ||
3385 | } | ||
3386 | |||
3387 | if ((uint64_t) width * cpp > UINT_MAX) | ||
3388 | return -ERANGE; | ||
3389 | |||
3390 | if ((uint64_t) height * r->pitches[i] + r->offsets[i] > UINT_MAX) | ||
3391 | return -ERANGE; | ||
3392 | |||
3393 | if (r->pitches[i] < width * cpp) { | ||
3394 | DRM_DEBUG_KMS("bad pitch %u for plane %d\n", r->pitches[i], i); | ||
3395 | return -EINVAL; | ||
3396 | } | ||
3397 | |||
3398 | if (r->modifier[i] && !(r->flags & DRM_MODE_FB_MODIFIERS)) { | ||
3399 | DRM_DEBUG_KMS("bad fb modifier %llu for plane %d\n", | ||
3400 | r->modifier[i], i); | ||
3401 | return -EINVAL; | ||
3402 | } | ||
3403 | |||
3404 | /* modifier specific checks: */ | ||
3405 | switch (r->modifier[i]) { | ||
3406 | case DRM_FORMAT_MOD_SAMSUNG_64_32_TILE: | ||
3407 | /* NOTE: the pitch restriction may be lifted later if it turns | ||
3408 | * out that no hw has this restriction: | ||
3409 | */ | ||
3410 | if (r->pixel_format != DRM_FORMAT_NV12 || | ||
3411 | width % 128 || height % 32 || | ||
3412 | r->pitches[i] % 128) { | ||
3413 | DRM_DEBUG_KMS("bad modifier data for plane %d\n", i); | ||
3414 | return -EINVAL; | ||
3415 | } | ||
3416 | break; | ||
3417 | |||
3418 | default: | ||
3419 | break; | ||
3420 | } | ||
3421 | } | ||
3422 | |||
3423 | for (i = num_planes; i < 4; i++) { | ||
3424 | if (r->modifier[i]) { | ||
3425 | DRM_DEBUG_KMS("non-zero modifier for unused plane %d\n", i); | ||
3426 | return -EINVAL; | ||
3427 | } | ||
3428 | |||
3429 | /* Pre-FB_MODIFIERS userspace didn't clear the structs properly. */ | ||
3430 | if (!(r->flags & DRM_MODE_FB_MODIFIERS)) | ||
3431 | continue; | ||
3432 | |||
3433 | if (r->handles[i]) { | ||
3434 | DRM_DEBUG_KMS("buffer object handle for unused plane %d\n", i); | ||
3435 | return -EINVAL; | ||
3436 | } | ||
3437 | |||
3438 | if (r->pitches[i]) { | ||
3439 | DRM_DEBUG_KMS("non-zero pitch for unused plane %d\n", i); | ||
3440 | return -EINVAL; | ||
3441 | } | ||
3442 | |||
3443 | if (r->offsets[i]) { | ||
3444 | DRM_DEBUG_KMS("non-zero offset for unused plane %d\n", i); | ||
3445 | return -EINVAL; | ||
3446 | } | ||
3447 | } | ||
3448 | |||
3449 | return 0; | ||
3450 | } | ||
3451 | |||
3452 | static struct drm_framebuffer * | ||
3453 | internal_framebuffer_create(struct drm_device *dev, | ||
3454 | const struct drm_mode_fb_cmd2 *r, | ||
3455 | struct drm_file *file_priv) | ||
3456 | { | ||
3457 | struct drm_mode_config *config = &dev->mode_config; | ||
3458 | struct drm_framebuffer *fb; | ||
3459 | int ret; | ||
3460 | |||
3461 | if (r->flags & ~(DRM_MODE_FB_INTERLACED | DRM_MODE_FB_MODIFIERS)) { | ||
3462 | DRM_DEBUG_KMS("bad framebuffer flags 0x%08x\n", r->flags); | ||
3463 | return ERR_PTR(-EINVAL); | ||
3464 | } | ||
3465 | |||
3466 | if ((config->min_width > r->width) || (r->width > config->max_width)) { | ||
3467 | DRM_DEBUG_KMS("bad framebuffer width %d, should be >= %d && <= %d\n", | ||
3468 | r->width, config->min_width, config->max_width); | ||
3469 | return ERR_PTR(-EINVAL); | ||
3470 | } | ||
3471 | if ((config->min_height > r->height) || (r->height > config->max_height)) { | ||
3472 | DRM_DEBUG_KMS("bad framebuffer height %d, should be >= %d && <= %d\n", | ||
3473 | r->height, config->min_height, config->max_height); | ||
3474 | return ERR_PTR(-EINVAL); | ||
3475 | } | ||
3476 | |||
3477 | if (r->flags & DRM_MODE_FB_MODIFIERS && | ||
3478 | !dev->mode_config.allow_fb_modifiers) { | ||
3479 | DRM_DEBUG_KMS("driver does not support fb modifiers\n"); | ||
3480 | return ERR_PTR(-EINVAL); | ||
3481 | } | ||
3482 | |||
3483 | ret = framebuffer_check(r); | ||
3484 | if (ret) | ||
3485 | return ERR_PTR(ret); | ||
3486 | |||
3487 | fb = dev->mode_config.funcs->fb_create(dev, file_priv, r); | ||
3488 | if (IS_ERR(fb)) { | ||
3489 | DRM_DEBUG_KMS("could not create framebuffer\n"); | ||
3490 | return fb; | ||
3491 | } | ||
3492 | |||
3493 | return fb; | ||
3494 | } | ||
3495 | |||
3496 | /** | ||
3497 | * drm_mode_addfb2 - add an FB to the graphics configuration | ||
3498 | * @dev: drm device for the ioctl | ||
3499 | * @data: data pointer for the ioctl | ||
3500 | * @file_priv: drm file for the ioctl call | ||
3501 | * | ||
3502 | * Add a new FB to the specified CRTC, given a user request with format. This is | ||
3503 | * the 2nd version of the addfb ioctl, which supports multi-planar framebuffers | ||
3504 | * and uses fourcc codes as pixel format specifiers. | ||
3505 | * | ||
3506 | * Called by the user via ioctl. | ||
3507 | * | ||
3508 | * Returns: | ||
3509 | * Zero on success, negative errno on failure. | ||
3510 | */ | ||
3511 | int drm_mode_addfb2(struct drm_device *dev, | ||
3512 | void *data, struct drm_file *file_priv) | ||
3513 | { | ||
3514 | struct drm_mode_fb_cmd2 *r = data; | ||
3515 | struct drm_framebuffer *fb; | ||
3516 | |||
3517 | if (!drm_core_check_feature(dev, DRIVER_MODESET)) | ||
3518 | return -EINVAL; | ||
3519 | |||
3520 | fb = internal_framebuffer_create(dev, r, file_priv); | ||
3521 | if (IS_ERR(fb)) | ||
3522 | return PTR_ERR(fb); | ||
3523 | |||
3524 | DRM_DEBUG_KMS("[FB:%d]\n", fb->base.id); | ||
3525 | r->fb_id = fb->base.id; | ||
3526 | |||
3527 | /* Transfer ownership to the filp for reaping on close */ | ||
3528 | mutex_lock(&file_priv->fbs_lock); | ||
3529 | list_add(&fb->filp_head, &file_priv->fbs); | ||
3530 | mutex_unlock(&file_priv->fbs_lock); | ||
3531 | |||
3532 | return 0; | ||
3533 | } | ||
3534 | |||
3535 | struct drm_mode_rmfb_work { | ||
3536 | struct work_struct work; | ||
3537 | struct list_head fbs; | ||
3538 | }; | ||
3539 | |||
3540 | static void drm_mode_rmfb_work_fn(struct work_struct *w) | ||
3541 | { | ||
3542 | struct drm_mode_rmfb_work *arg = container_of(w, typeof(*arg), work); | ||
3543 | |||
3544 | while (!list_empty(&arg->fbs)) { | ||
3545 | struct drm_framebuffer *fb = | ||
3546 | list_first_entry(&arg->fbs, typeof(*fb), filp_head); | ||
3547 | |||
3548 | list_del_init(&fb->filp_head); | ||
3549 | drm_framebuffer_remove(fb); | ||
3550 | } | ||
3551 | } | ||
3552 | |||
3553 | /** | ||
3554 | * drm_mode_rmfb - remove an FB from the configuration | ||
3555 | * @dev: drm device for the ioctl | ||
3556 | * @data: data pointer for the ioctl | ||
3557 | * @file_priv: drm file for the ioctl call | ||
3558 | * | ||
3559 | * Remove the FB specified by the user. | ||
3560 | * | ||
3561 | * Called by the user via ioctl. | ||
3562 | * | ||
3563 | * Returns: | ||
3564 | * Zero on success, negative errno on failure. | ||
3565 | */ | ||
3566 | int drm_mode_rmfb(struct drm_device *dev, | ||
3567 | void *data, struct drm_file *file_priv) | ||
3568 | { | ||
3569 | struct drm_framebuffer *fb = NULL; | ||
3570 | struct drm_framebuffer *fbl = NULL; | ||
3571 | uint32_t *id = data; | ||
3572 | int found = 0; | ||
3573 | |||
3574 | if (!drm_core_check_feature(dev, DRIVER_MODESET)) | ||
3575 | return -EINVAL; | ||
3576 | |||
3577 | fb = drm_framebuffer_lookup(dev, *id); | ||
3578 | if (!fb) | ||
3579 | return -ENOENT; | ||
3580 | |||
3581 | mutex_lock(&file_priv->fbs_lock); | ||
3582 | list_for_each_entry(fbl, &file_priv->fbs, filp_head) | ||
3583 | if (fb == fbl) | ||
3584 | found = 1; | ||
3585 | if (!found) { | ||
3586 | mutex_unlock(&file_priv->fbs_lock); | ||
3587 | goto fail_unref; | ||
3588 | } | ||
3589 | |||
3590 | list_del_init(&fb->filp_head); | ||
3591 | mutex_unlock(&file_priv->fbs_lock); | ||
3592 | |||
3593 | /* drop the reference we picked up in framebuffer lookup */ | ||
3594 | drm_framebuffer_unreference(fb); | ||
3595 | |||
3596 | /* | ||
3597 | * we now own the reference that was stored in the fbs list | ||
3598 | * | ||
3599 | * drm_framebuffer_remove may fail with -EINTR on pending signals, | ||
3600 | * so run this in a separate stack as there's no way to correctly | ||
3601 | * handle this after the fb is already removed from the lookup table. | ||
3602 | */ | ||
3603 | if (drm_framebuffer_read_refcount(fb) > 1) { | ||
3604 | struct drm_mode_rmfb_work arg; | ||
3605 | |||
3606 | INIT_WORK_ONSTACK(&arg.work, drm_mode_rmfb_work_fn); | ||
3607 | INIT_LIST_HEAD(&arg.fbs); | ||
3608 | list_add_tail(&fb->filp_head, &arg.fbs); | ||
3609 | |||
3610 | schedule_work(&arg.work); | ||
3611 | flush_work(&arg.work); | ||
3612 | destroy_work_on_stack(&arg.work); | ||
3613 | } else | ||
3614 | drm_framebuffer_unreference(fb); | ||
3615 | |||
3616 | return 0; | ||
3617 | |||
3618 | fail_unref: | ||
3619 | drm_framebuffer_unreference(fb); | ||
3620 | return -ENOENT; | ||
3621 | } | ||
3622 | |||
3623 | /** | ||
3624 | * drm_mode_getfb - get FB info | ||
3625 | * @dev: drm device for the ioctl | ||
3626 | * @data: data pointer for the ioctl | ||
3627 | * @file_priv: drm file for the ioctl call | ||
3628 | * | ||
3629 | * Lookup the FB given its ID and return info about it. | ||
3630 | * | ||
3631 | * Called by the user via ioctl. | ||
3632 | * | ||
3633 | * Returns: | ||
3634 | * Zero on success, negative errno on failure. | ||
3635 | */ | ||
3636 | int drm_mode_getfb(struct drm_device *dev, | ||
3637 | void *data, struct drm_file *file_priv) | ||
3638 | { | ||
3639 | struct drm_mode_fb_cmd *r = data; | ||
3640 | struct drm_framebuffer *fb; | ||
3641 | int ret; | ||
3642 | |||
3643 | if (!drm_core_check_feature(dev, DRIVER_MODESET)) | ||
3644 | return -EINVAL; | ||
3645 | |||
3646 | fb = drm_framebuffer_lookup(dev, r->fb_id); | ||
3647 | if (!fb) | ||
3648 | return -ENOENT; | ||
3649 | |||
3650 | r->height = fb->height; | ||
3651 | r->width = fb->width; | ||
3652 | r->depth = fb->depth; | ||
3653 | r->bpp = fb->bits_per_pixel; | ||
3654 | r->pitch = fb->pitches[0]; | ||
3655 | if (fb->funcs->create_handle) { | ||
3656 | if (drm_is_current_master(file_priv) || capable(CAP_SYS_ADMIN) || | ||
3657 | drm_is_control_client(file_priv)) { | ||
3658 | ret = fb->funcs->create_handle(fb, file_priv, | ||
3659 | &r->handle); | ||
3660 | } else { | ||
3661 | /* GET_FB() is an unprivileged ioctl so we must not | ||
3662 | * return a buffer-handle to non-master processes! For | ||
3663 | * backwards-compatibility reasons, we cannot make | ||
3664 | * GET_FB() privileged, so just return an invalid handle | ||
3665 | * for non-masters. */ | ||
3666 | r->handle = 0; | ||
3667 | ret = 0; | ||
3668 | } | ||
3669 | } else { | ||
3670 | ret = -ENODEV; | ||
3671 | } | ||
3672 | |||
3673 | drm_framebuffer_unreference(fb); | ||
3674 | |||
3675 | return ret; | ||
3676 | } | ||
3677 | |||
3678 | /** | ||
3679 | * drm_mode_dirtyfb_ioctl - flush frontbuffer rendering on an FB | ||
3680 | * @dev: drm device for the ioctl | ||
3681 | * @data: data pointer for the ioctl | ||
3682 | * @file_priv: drm file for the ioctl call | ||
3683 | * | ||
3684 | * Lookup the FB and flush out the damaged area supplied by userspace as a clip | ||
3685 | * rectangle list. Generic userspace which does frontbuffer rendering must call | ||
3686 | * this ioctl to flush out the changes on manual-update display outputs, e.g. | ||
3687 | * usb display-link, mipi manual update panels or edp panel self refresh modes. | ||
3688 | * | ||
3689 | * Modesetting drivers which always update the frontbuffer do not need to | ||
3690 | * implement the corresponding ->dirty framebuffer callback. | ||
3691 | * | ||
3692 | * Called by the user via ioctl. | ||
3693 | * | ||
3694 | * Returns: | ||
3695 | * Zero on success, negative errno on failure. | ||
3696 | */ | ||
3697 | int drm_mode_dirtyfb_ioctl(struct drm_device *dev, | ||
3698 | void *data, struct drm_file *file_priv) | ||
3699 | { | ||
3700 | struct drm_clip_rect __user *clips_ptr; | ||
3701 | struct drm_clip_rect *clips = NULL; | ||
3702 | struct drm_mode_fb_dirty_cmd *r = data; | ||
3703 | struct drm_framebuffer *fb; | ||
3704 | unsigned flags; | ||
3705 | int num_clips; | ||
3706 | int ret; | ||
3707 | |||
3708 | if (!drm_core_check_feature(dev, DRIVER_MODESET)) | ||
3709 | return -EINVAL; | ||
3710 | |||
3711 | fb = drm_framebuffer_lookup(dev, r->fb_id); | ||
3712 | if (!fb) | ||
3713 | return -ENOENT; | ||
3714 | |||
3715 | num_clips = r->num_clips; | ||
3716 | clips_ptr = (struct drm_clip_rect __user *)(unsigned long)r->clips_ptr; | ||
3717 | |||
3718 | if (!num_clips != !clips_ptr) { | ||
3719 | ret = -EINVAL; | ||
3720 | goto out_err1; | ||
3721 | } | ||
3722 | |||
3723 | flags = DRM_MODE_FB_DIRTY_FLAGS & r->flags; | ||
3724 | |||
3725 | /* If userspace annotates copy, clips must come in pairs */ | ||
3726 | if (flags & DRM_MODE_FB_DIRTY_ANNOTATE_COPY && (num_clips % 2)) { | ||
3727 | ret = -EINVAL; | ||
3728 | goto out_err1; | ||
3729 | } | ||
3730 | |||
3731 | if (num_clips && clips_ptr) { | ||
3732 | if (num_clips < 0 || num_clips > DRM_MODE_FB_DIRTY_MAX_CLIPS) { | ||
3733 | ret = -EINVAL; | ||
3734 | goto out_err1; | ||
3735 | } | ||
3736 | clips = kcalloc(num_clips, sizeof(*clips), GFP_KERNEL); | ||
3737 | if (!clips) { | ||
3738 | ret = -ENOMEM; | ||
3739 | goto out_err1; | ||
3740 | } | ||
3741 | |||
3742 | ret = copy_from_user(clips, clips_ptr, | ||
3743 | num_clips * sizeof(*clips)); | ||
3744 | if (ret) { | ||
3745 | ret = -EFAULT; | ||
3746 | goto out_err2; | ||
3747 | } | ||
3748 | } | ||
3749 | |||
3750 | if (fb->funcs->dirty) { | ||
3751 | ret = fb->funcs->dirty(fb, file_priv, flags, r->color, | ||
3752 | clips, num_clips); | ||
3753 | } else { | ||
3754 | ret = -ENOSYS; | ||
3755 | } | ||
3756 | |||
3757 | out_err2: | ||
3758 | kfree(clips); | ||
3759 | out_err1: | ||
3760 | drm_framebuffer_unreference(fb); | ||
3761 | |||
3762 | return ret; | ||
3763 | } | ||
3764 | |||
3765 | /** | ||
3766 | * drm_fb_release - remove and free the FBs on this file | ||
3767 | * @priv: drm file for the ioctl | ||
3768 | * | ||
3769 | * Destroy all the FBs associated with @filp. | ||
3770 | * | ||
3771 | * Called by the user via ioctl. | ||
3772 | * | ||
3773 | * Returns: | ||
3774 | * Zero on success, negative errno on failure. | ||
3775 | */ | ||
3776 | void drm_fb_release(struct drm_file *priv) | ||
3777 | { | ||
3778 | struct drm_framebuffer *fb, *tfb; | ||
3779 | struct drm_mode_rmfb_work arg; | ||
3780 | |||
3781 | INIT_LIST_HEAD(&arg.fbs); | ||
3782 | |||
3783 | /* | ||
3784 | * When the file gets released that means no one else can access the fb | ||
3785 | * list any more, so no need to grab fpriv->fbs_lock. And we need to | ||
3786 | * avoid upsetting lockdep since the universal cursor code adds a | ||
3787 | * framebuffer while holding mutex locks. | ||
3788 | * | ||
3789 | * Note that a real deadlock between fpriv->fbs_lock and the modeset | ||
3790 | * locks is impossible here since no one else but this function can get | ||
3791 | * at it any more. | ||
3792 | */ | ||
3793 | list_for_each_entry_safe(fb, tfb, &priv->fbs, filp_head) { | ||
3794 | if (drm_framebuffer_read_refcount(fb) > 1) { | ||
3795 | list_move_tail(&fb->filp_head, &arg.fbs); | ||
3796 | } else { | ||
3797 | list_del_init(&fb->filp_head); | ||
3798 | |||
3799 | /* This drops the fpriv->fbs reference. */ | ||
3800 | drm_framebuffer_unreference(fb); | ||
3801 | } | ||
3802 | } | ||
3803 | |||
3804 | if (!list_empty(&arg.fbs)) { | ||
3805 | INIT_WORK_ONSTACK(&arg.work, drm_mode_rmfb_work_fn); | ||
3806 | |||
3807 | schedule_work(&arg.work); | ||
3808 | flush_work(&arg.work); | ||
3809 | destroy_work_on_stack(&arg.work); | ||
3810 | } | ||
3811 | } | ||
3812 | |||
3813 | static bool drm_property_type_valid(struct drm_property *property) | 2105 | static bool drm_property_type_valid(struct drm_property *property) |
3814 | { | 2106 | { |
3815 | if (property->flags & DRM_MODE_PROP_EXTENDED_TYPE) | 2107 | if (property->flags & DRM_MODE_PROP_EXTENDED_TYPE) |
@@ -4522,7 +2814,7 @@ struct drm_property_blob *drm_property_lookup_blob(struct drm_device *dev, | |||
4522 | struct drm_mode_object *obj; | 2814 | struct drm_mode_object *obj; |
4523 | struct drm_property_blob *blob = NULL; | 2815 | struct drm_property_blob *blob = NULL; |
4524 | 2816 | ||
4525 | obj = _object_find(dev, id, DRM_MODE_OBJECT_BLOB); | 2817 | obj = __drm_mode_object_find(dev, id, DRM_MODE_OBJECT_BLOB); |
4526 | if (obj) | 2818 | if (obj) |
4527 | blob = obj_to_blob(obj); | 2819 | blob = obj_to_blob(obj); |
4528 | return blob; | 2820 | return blob; |
@@ -4559,12 +2851,12 @@ EXPORT_SYMBOL(drm_property_lookup_blob); | |||
4559 | * a completely atomic update. The access to path_blob_ptr is protected by the | 2851 | * a completely atomic update. The access to path_blob_ptr is protected by the |
4560 | * caller holding a lock on the connector. | 2852 | * caller holding a lock on the connector. |
4561 | */ | 2853 | */ |
4562 | static int drm_property_replace_global_blob(struct drm_device *dev, | 2854 | int drm_property_replace_global_blob(struct drm_device *dev, |
4563 | struct drm_property_blob **replace, | 2855 | struct drm_property_blob **replace, |
4564 | size_t length, | 2856 | size_t length, |
4565 | const void *data, | 2857 | const void *data, |
4566 | struct drm_mode_object *obj_holds_id, | 2858 | struct drm_mode_object *obj_holds_id, |
4567 | struct drm_property *prop_holds_id) | 2859 | struct drm_property *prop_holds_id) |
4568 | { | 2860 | { |
4569 | struct drm_property_blob *new_blob = NULL; | 2861 | struct drm_property_blob *new_blob = NULL; |
4570 | struct drm_property_blob *old_blob = NULL; | 2862 | struct drm_property_blob *old_blob = NULL; |
@@ -4603,6 +2895,7 @@ err_created: | |||
4603 | drm_property_unreference_blob(new_blob); | 2895 | drm_property_unreference_blob(new_blob); |
4604 | return ret; | 2896 | return ret; |
4605 | } | 2897 | } |
2898 | EXPORT_SYMBOL(drm_property_replace_global_blob); | ||
4606 | 2899 | ||
4607 | /** | 2900 | /** |
4608 | * drm_mode_getblob_ioctl - get the contents of a blob property value | 2901 | * drm_mode_getblob_ioctl - get the contents of a blob property value |
@@ -4758,113 +3051,6 @@ err: | |||
4758 | return ret; | 3051 | return ret; |
4759 | } | 3052 | } |
4760 | 3053 | ||
4761 | /** | ||
4762 | * drm_mode_connector_set_path_property - set tile property on connector | ||
4763 | * @connector: connector to set property on. | ||
4764 | * @path: path to use for property; must not be NULL. | ||
4765 | * | ||
4766 | * This creates a property to expose to userspace to specify a | ||
4767 | * connector path. This is mainly used for DisplayPort MST where | ||
4768 | * connectors have a topology and we want to allow userspace to give | ||
4769 | * them more meaningful names. | ||
4770 | * | ||
4771 | * Returns: | ||
4772 | * Zero on success, negative errno on failure. | ||
4773 | */ | ||
4774 | int drm_mode_connector_set_path_property(struct drm_connector *connector, | ||
4775 | const char *path) | ||
4776 | { | ||
4777 | struct drm_device *dev = connector->dev; | ||
4778 | int ret; | ||
4779 | |||
4780 | ret = drm_property_replace_global_blob(dev, | ||
4781 | &connector->path_blob_ptr, | ||
4782 | strlen(path) + 1, | ||
4783 | path, | ||
4784 | &connector->base, | ||
4785 | dev->mode_config.path_property); | ||
4786 | return ret; | ||
4787 | } | ||
4788 | EXPORT_SYMBOL(drm_mode_connector_set_path_property); | ||
4789 | |||
4790 | /** | ||
4791 | * drm_mode_connector_set_tile_property - set tile property on connector | ||
4792 | * @connector: connector to set property on. | ||
4793 | * | ||
4794 | * This looks up the tile information for a connector, and creates a | ||
4795 | * property for userspace to parse if it exists. The property is of | ||
4796 | * the form of 8 integers using ':' as a separator. | ||
4797 | * | ||
4798 | * Returns: | ||
4799 | * Zero on success, errno on failure. | ||
4800 | */ | ||
4801 | int drm_mode_connector_set_tile_property(struct drm_connector *connector) | ||
4802 | { | ||
4803 | struct drm_device *dev = connector->dev; | ||
4804 | char tile[256]; | ||
4805 | int ret; | ||
4806 | |||
4807 | if (!connector->has_tile) { | ||
4808 | ret = drm_property_replace_global_blob(dev, | ||
4809 | &connector->tile_blob_ptr, | ||
4810 | 0, | ||
4811 | NULL, | ||
4812 | &connector->base, | ||
4813 | dev->mode_config.tile_property); | ||
4814 | return ret; | ||
4815 | } | ||
4816 | |||
4817 | snprintf(tile, 256, "%d:%d:%d:%d:%d:%d:%d:%d", | ||
4818 | connector->tile_group->id, connector->tile_is_single_monitor, | ||
4819 | connector->num_h_tile, connector->num_v_tile, | ||
4820 | connector->tile_h_loc, connector->tile_v_loc, | ||
4821 | connector->tile_h_size, connector->tile_v_size); | ||
4822 | |||
4823 | ret = drm_property_replace_global_blob(dev, | ||
4824 | &connector->tile_blob_ptr, | ||
4825 | strlen(tile) + 1, | ||
4826 | tile, | ||
4827 | &connector->base, | ||
4828 | dev->mode_config.tile_property); | ||
4829 | return ret; | ||
4830 | } | ||
4831 | EXPORT_SYMBOL(drm_mode_connector_set_tile_property); | ||
4832 | |||
4833 | /** | ||
4834 | * drm_mode_connector_update_edid_property - update the edid property of a connector | ||
4835 | * @connector: drm connector | ||
4836 | * @edid: new value of the edid property | ||
4837 | * | ||
4838 | * This function creates a new blob modeset object and assigns its id to the | ||
4839 | * connector's edid property. | ||
4840 | * | ||
4841 | * Returns: | ||
4842 | * Zero on success, negative errno on failure. | ||
4843 | */ | ||
4844 | int drm_mode_connector_update_edid_property(struct drm_connector *connector, | ||
4845 | const struct edid *edid) | ||
4846 | { | ||
4847 | struct drm_device *dev = connector->dev; | ||
4848 | size_t size = 0; | ||
4849 | int ret; | ||
4850 | |||
4851 | /* ignore requests to set edid when overridden */ | ||
4852 | if (connector->override_edid) | ||
4853 | return 0; | ||
4854 | |||
4855 | if (edid) | ||
4856 | size = EDID_LENGTH * (1 + edid->extensions); | ||
4857 | |||
4858 | ret = drm_property_replace_global_blob(dev, | ||
4859 | &connector->edid_blob_ptr, | ||
4860 | size, | ||
4861 | edid, | ||
4862 | &connector->base, | ||
4863 | dev->mode_config.edid_property); | ||
4864 | return ret; | ||
4865 | } | ||
4866 | EXPORT_SYMBOL(drm_mode_connector_update_edid_property); | ||
4867 | |||
4868 | /* Some properties could refer to dynamic refcnt'd objects, or things that | 3054 | /* Some properties could refer to dynamic refcnt'd objects, or things that |
4869 | * need special locking to handle lifetime issues (ie. to ensure the prop | 3055 | * need special locking to handle lifetime issues (ie. to ensure the prop |
4870 | * value doesn't become invalid part way through the property update due to | 3056 | * value doesn't become invalid part way through the property update due to |
@@ -4918,7 +3104,8 @@ bool drm_property_change_valid_get(struct drm_property *property, | |||
4918 | if (value == 0) | 3104 | if (value == 0) |
4919 | return true; | 3105 | return true; |
4920 | 3106 | ||
4921 | *ref = _object_find(property->dev, value, property->values[0]); | 3107 | *ref = __drm_mode_object_find(property->dev, value, |
3108 | property->values[0]); | ||
4922 | return *ref != NULL; | 3109 | return *ref != NULL; |
4923 | } | 3110 | } |
4924 | 3111 | ||
@@ -4940,54 +3127,6 @@ void drm_property_change_valid_put(struct drm_property *property, | |||
4940 | drm_property_unreference_blob(obj_to_blob(ref)); | 3127 | drm_property_unreference_blob(obj_to_blob(ref)); |
4941 | } | 3128 | } |
4942 | 3129 | ||
4943 | /** | ||
4944 | * drm_mode_connector_property_set_ioctl - set the current value of a connector property | ||
4945 | * @dev: DRM device | ||
4946 | * @data: ioctl data | ||
4947 | * @file_priv: DRM file info | ||
4948 | * | ||
4949 | * This function sets the current value for a connectors's property. It also | ||
4950 | * calls into a driver's ->set_property callback to update the hardware state | ||
4951 | * | ||
4952 | * Called by the user via ioctl. | ||
4953 | * | ||
4954 | * Returns: | ||
4955 | * Zero on success, negative errno on failure. | ||
4956 | */ | ||
4957 | int drm_mode_connector_property_set_ioctl(struct drm_device *dev, | ||
4958 | void *data, struct drm_file *file_priv) | ||
4959 | { | ||
4960 | struct drm_mode_connector_set_property *conn_set_prop = data; | ||
4961 | struct drm_mode_obj_set_property obj_set_prop = { | ||
4962 | .value = conn_set_prop->value, | ||
4963 | .prop_id = conn_set_prop->prop_id, | ||
4964 | .obj_id = conn_set_prop->connector_id, | ||
4965 | .obj_type = DRM_MODE_OBJECT_CONNECTOR | ||
4966 | }; | ||
4967 | |||
4968 | /* It does all the locking and checking we need */ | ||
4969 | return drm_mode_obj_set_property_ioctl(dev, &obj_set_prop, file_priv); | ||
4970 | } | ||
4971 | |||
4972 | static int drm_mode_connector_set_obj_prop(struct drm_mode_object *obj, | ||
4973 | struct drm_property *property, | ||
4974 | uint64_t value) | ||
4975 | { | ||
4976 | int ret = -EINVAL; | ||
4977 | struct drm_connector *connector = obj_to_connector(obj); | ||
4978 | |||
4979 | /* Do DPMS ourselves */ | ||
4980 | if (property == connector->dev->mode_config.dpms_property) { | ||
4981 | ret = (*connector->funcs->dpms)(connector, (int)value); | ||
4982 | } else if (connector->funcs->set_property) | ||
4983 | ret = connector->funcs->set_property(connector, property, value); | ||
4984 | |||
4985 | /* store the property value if successful */ | ||
4986 | if (!ret) | ||
4987 | drm_object_property_set_value(&connector->base, property, value); | ||
4988 | return ret; | ||
4989 | } | ||
4990 | |||
4991 | static int drm_mode_crtc_set_obj_prop(struct drm_mode_object *obj, | 3130 | static int drm_mode_crtc_set_obj_prop(struct drm_mode_object *obj, |
4992 | struct drm_property *property, | 3131 | struct drm_property *property, |
4993 | uint64_t value) | 3132 | uint64_t value) |
@@ -5069,7 +3208,7 @@ int drm_mode_obj_get_properties_ioctl(struct drm_device *dev, void *data, | |||
5069 | goto out_unref; | 3208 | goto out_unref; |
5070 | } | 3209 | } |
5071 | 3210 | ||
5072 | ret = get_properties(obj, file_priv->atomic, | 3211 | ret = drm_mode_object_get_properties(obj, file_priv->atomic, |
5073 | (uint32_t __user *)(unsigned long)(arg->props_ptr), | 3212 | (uint32_t __user *)(unsigned long)(arg->props_ptr), |
5074 | (uint64_t __user *)(unsigned long)(arg->prop_values_ptr), | 3213 | (uint64_t __user *)(unsigned long)(arg->prop_values_ptr), |
5075 | &arg->count_props); | 3214 | &arg->count_props); |
@@ -5081,22 +3220,6 @@ out: | |||
5081 | return ret; | 3220 | return ret; |
5082 | } | 3221 | } |
5083 | 3222 | ||
5084 | /** | ||
5085 | * drm_mode_obj_set_property_ioctl - set the current value of an object's property | ||
5086 | * @dev: DRM device | ||
5087 | * @data: ioctl data | ||
5088 | * @file_priv: DRM file info | ||
5089 | * | ||
5090 | * This function sets the current value for an object's property. It also calls | ||
5091 | * into a driver's ->set_property callback to update the hardware state. | ||
5092 | * Compared to the connector specific ioctl this one is extended to also work on | ||
5093 | * crtc and plane objects. | ||
5094 | * | ||
5095 | * Called by the user via ioctl. | ||
5096 | * | ||
5097 | * Returns: | ||
5098 | * Zero on success, negative errno on failure. | ||
5099 | */ | ||
5100 | int drm_mode_obj_set_property_ioctl(struct drm_device *dev, void *data, | 3223 | int drm_mode_obj_set_property_ioctl(struct drm_device *dev, void *data, |
5101 | struct drm_file *file_priv) | 3224 | struct drm_file *file_priv) |
5102 | { | 3225 | { |
@@ -5162,47 +3285,6 @@ out: | |||
5162 | } | 3285 | } |
5163 | 3286 | ||
5164 | /** | 3287 | /** |
5165 | * drm_mode_connector_attach_encoder - attach a connector to an encoder | ||
5166 | * @connector: connector to attach | ||
5167 | * @encoder: encoder to attach @connector to | ||
5168 | * | ||
5169 | * This function links up a connector to an encoder. Note that the routing | ||
5170 | * restrictions between encoders and crtcs are exposed to userspace through the | ||
5171 | * possible_clones and possible_crtcs bitmasks. | ||
5172 | * | ||
5173 | * Returns: | ||
5174 | * Zero on success, negative errno on failure. | ||
5175 | */ | ||
5176 | int drm_mode_connector_attach_encoder(struct drm_connector *connector, | ||
5177 | struct drm_encoder *encoder) | ||
5178 | { | ||
5179 | int i; | ||
5180 | |||
5181 | /* | ||
5182 | * In the past, drivers have attempted to model the static association | ||
5183 | * of connector to encoder in simple connector/encoder devices using a | ||
5184 | * direct assignment of connector->encoder = encoder. This connection | ||
5185 | * is a logical one and the responsibility of the core, so drivers are | ||
5186 | * expected not to mess with this. | ||
5187 | * | ||
5188 | * Note that the error return should've been enough here, but a large | ||
5189 | * majority of drivers ignores the return value, so add in a big WARN | ||
5190 | * to get people's attention. | ||
5191 | */ | ||
5192 | if (WARN_ON(connector->encoder)) | ||
5193 | return -EINVAL; | ||
5194 | |||
5195 | for (i = 0; i < DRM_CONNECTOR_MAX_ENCODER; i++) { | ||
5196 | if (connector->encoder_ids[i] == 0) { | ||
5197 | connector->encoder_ids[i] = encoder->base.id; | ||
5198 | return 0; | ||
5199 | } | ||
5200 | } | ||
5201 | return -ENOMEM; | ||
5202 | } | ||
5203 | EXPORT_SYMBOL(drm_mode_connector_attach_encoder); | ||
5204 | |||
5205 | /** | ||
5206 | * drm_mode_crtc_set_gamma_size - set the gamma table size | 3288 | * drm_mode_crtc_set_gamma_size - set the gamma table size |
5207 | * @crtc: CRTC to set the gamma table size for | 3289 | * @crtc: CRTC to set the gamma table size for |
5208 | * @gamma_size: size of the gamma table | 3290 | * @gamma_size: size of the gamma table |
diff --git a/drivers/gpu/drm/drm_crtc_helper.c b/drivers/gpu/drm/drm_crtc_helper.c index 604d3ef72ffa..5d2cb138eba6 100644 --- a/drivers/gpu/drm/drm_crtc_helper.c +++ b/drivers/gpu/drm/drm_crtc_helper.c | |||
@@ -75,35 +75,6 @@ | |||
75 | */ | 75 | */ |
76 | 76 | ||
77 | /** | 77 | /** |
78 | * drm_helper_move_panel_connectors_to_head() - move panels to the front in the | ||
79 | * connector list | ||
80 | * @dev: drm device to operate on | ||
81 | * | ||
82 | * Some userspace presumes that the first connected connector is the main | ||
83 | * display, where it's supposed to display e.g. the login screen. For | ||
84 | * laptops, this should be the main panel. Use this function to sort all | ||
85 | * (eDP/LVDS) panels to the front of the connector list, instead of | ||
86 | * painstakingly trying to initialize them in the right order. | ||
87 | */ | ||
88 | void drm_helper_move_panel_connectors_to_head(struct drm_device *dev) | ||
89 | { | ||
90 | struct drm_connector *connector, *tmp; | ||
91 | struct list_head panel_list; | ||
92 | |||
93 | INIT_LIST_HEAD(&panel_list); | ||
94 | |||
95 | list_for_each_entry_safe(connector, tmp, | ||
96 | &dev->mode_config.connector_list, head) { | ||
97 | if (connector->connector_type == DRM_MODE_CONNECTOR_LVDS || | ||
98 | connector->connector_type == DRM_MODE_CONNECTOR_eDP) | ||
99 | list_move_tail(&connector->head, &panel_list); | ||
100 | } | ||
101 | |||
102 | list_splice(&panel_list, &dev->mode_config.connector_list); | ||
103 | } | ||
104 | EXPORT_SYMBOL(drm_helper_move_panel_connectors_to_head); | ||
105 | |||
106 | /** | ||
107 | * drm_helper_encoder_in_use - check if a given encoder is in use | 78 | * drm_helper_encoder_in_use - check if a given encoder is in use |
108 | * @encoder: encoder to check | 79 | * @encoder: encoder to check |
109 | * | 80 | * |
@@ -913,33 +884,6 @@ int drm_helper_connector_dpms(struct drm_connector *connector, int mode) | |||
913 | EXPORT_SYMBOL(drm_helper_connector_dpms); | 884 | EXPORT_SYMBOL(drm_helper_connector_dpms); |
914 | 885 | ||
915 | /** | 886 | /** |
916 | * drm_helper_mode_fill_fb_struct - fill out framebuffer metadata | ||
917 | * @fb: drm_framebuffer object to fill out | ||
918 | * @mode_cmd: metadata from the userspace fb creation request | ||
919 | * | ||
920 | * This helper can be used in a drivers fb_create callback to pre-fill the fb's | ||
921 | * metadata fields. | ||
922 | */ | ||
923 | void drm_helper_mode_fill_fb_struct(struct drm_framebuffer *fb, | ||
924 | const struct drm_mode_fb_cmd2 *mode_cmd) | ||
925 | { | ||
926 | int i; | ||
927 | |||
928 | fb->width = mode_cmd->width; | ||
929 | fb->height = mode_cmd->height; | ||
930 | for (i = 0; i < 4; i++) { | ||
931 | fb->pitches[i] = mode_cmd->pitches[i]; | ||
932 | fb->offsets[i] = mode_cmd->offsets[i]; | ||
933 | fb->modifier[i] = mode_cmd->modifier[i]; | ||
934 | } | ||
935 | drm_fb_get_bpp_depth(mode_cmd->pixel_format, &fb->depth, | ||
936 | &fb->bits_per_pixel); | ||
937 | fb->pixel_format = mode_cmd->pixel_format; | ||
938 | fb->flags = mode_cmd->flags; | ||
939 | } | ||
940 | EXPORT_SYMBOL(drm_helper_mode_fill_fb_struct); | ||
941 | |||
942 | /** | ||
943 | * drm_helper_resume_force_mode - force-restore mode setting configuration | 887 | * drm_helper_resume_force_mode - force-restore mode setting configuration |
944 | * @dev: drm_device which should be restored | 888 | * @dev: drm_device which should be restored |
945 | * | 889 | * |
diff --git a/include/drm/drm_dp_aux_dev.h b/drivers/gpu/drm/drm_crtc_helper_internal.h index 1b76d990d8ab..4e6b57ae7188 100644 --- a/include/drm/drm_dp_aux_dev.h +++ b/drivers/gpu/drm/drm_crtc_helper_internal.h | |||
@@ -1,5 +1,5 @@ | |||
1 | /* | 1 | /* |
2 | * Copyright © 2015 Intel Corporation | 2 | * Copyright © 2016 Intel Corporation |
3 | * | 3 | * |
4 | * Permission is hereby granted, free of charge, to any person obtaining a | 4 | * Permission is hereby granted, free of charge, to any person obtaining a |
5 | * copy of this software and associated documentation files (the "Software"), | 5 | * copy of this software and associated documentation files (the "Software"), |
@@ -8,37 +8,36 @@ | |||
8 | * and/or sell copies of the Software, and to permit persons to whom the | 8 | * and/or sell copies of the Software, and to permit persons to whom the |
9 | * Software is furnished to do so, subject to the following conditions: | 9 | * Software is furnished to do so, subject to the following conditions: |
10 | * | 10 | * |
11 | * The above copyright notice and this permission notice (including the next | 11 | * The above copyright notice and this permission notice shall be included in |
12 | * paragraph) shall be included in all copies or substantial portions of the | 12 | * all copies or substantial portions of the Software. |
13 | * Software. | ||
14 | * | 13 | * |
15 | * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR | 14 | * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR |
16 | * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, | 15 | * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, |
17 | * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL | 16 | * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL |
18 | * THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER | 17 | * THE COPYRIGHT HOLDER(S) OR AUTHOR(S) BE LIABLE FOR ANY CLAIM, DAMAGES OR |
19 | * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING | 18 | * OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, |
20 | * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS | 19 | * ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR |
21 | * IN THE SOFTWARE. | 20 | * OTHER DEALINGS IN THE SOFTWARE. |
22 | * | ||
23 | * Authors: | ||
24 | * Rafael Antognolli <rafael.antognolli@intel.com> | ||
25 | * | ||
26 | */ | 21 | */ |
27 | 22 | ||
28 | #ifndef DRM_DP_AUX_DEV | 23 | /* |
29 | #define DRM_DP_AUX_DEV | 24 | * This header file contains mode setting related functions and definitions |
25 | * which are only used within the drm kms helper module as internal | ||
26 | * implementation details and are not exported to drivers. | ||
27 | */ | ||
30 | 28 | ||
31 | #include <drm/drm_dp_helper.h> | 29 | #include <drm/drm_dp_helper.h> |
32 | 30 | ||
33 | #ifdef CONFIG_DRM_DP_AUX_CHARDEV | 31 | /* drm_fb_helper.c */ |
32 | int drm_fb_helper_modinit(void); | ||
34 | 33 | ||
34 | /* drm_dp_aux_dev.c */ | ||
35 | #ifdef CONFIG_DRM_DP_AUX_CHARDEV | ||
35 | int drm_dp_aux_dev_init(void); | 36 | int drm_dp_aux_dev_init(void); |
36 | void drm_dp_aux_dev_exit(void); | 37 | void drm_dp_aux_dev_exit(void); |
37 | int drm_dp_aux_register_devnode(struct drm_dp_aux *aux); | 38 | int drm_dp_aux_register_devnode(struct drm_dp_aux *aux); |
38 | void drm_dp_aux_unregister_devnode(struct drm_dp_aux *aux); | 39 | void drm_dp_aux_unregister_devnode(struct drm_dp_aux *aux); |
39 | |||
40 | #else | 40 | #else |
41 | |||
42 | static inline int drm_dp_aux_dev_init(void) | 41 | static inline int drm_dp_aux_dev_init(void) |
43 | { | 42 | { |
44 | return 0; | 43 | return 0; |
@@ -56,7 +55,4 @@ static inline int drm_dp_aux_register_devnode(struct drm_dp_aux *aux) | |||
56 | static inline void drm_dp_aux_unregister_devnode(struct drm_dp_aux *aux) | 55 | static inline void drm_dp_aux_unregister_devnode(struct drm_dp_aux *aux) |
57 | { | 56 | { |
58 | } | 57 | } |
59 | |||
60 | #endif | ||
61 | |||
62 | #endif | 58 | #endif |
diff --git a/drivers/gpu/drm/drm_crtc_internal.h b/drivers/gpu/drm/drm_crtc_internal.h index 0c34e6d906d1..62efb9d09a85 100644 --- a/drivers/gpu/drm/drm_crtc_internal.h +++ b/drivers/gpu/drm/drm_crtc_internal.h | |||
@@ -33,12 +33,23 @@ | |||
33 | 33 | ||
34 | 34 | ||
35 | /* drm_crtc.c */ | 35 | /* drm_crtc.c */ |
36 | void drm_connector_ida_init(void); | 36 | int drm_mode_object_get_reg(struct drm_device *dev, |
37 | void drm_connector_ida_destroy(void); | 37 | struct drm_mode_object *obj, |
38 | uint32_t obj_type, | ||
39 | bool register_obj, | ||
40 | void (*obj_free_cb)(struct kref *kref)); | ||
41 | void drm_mode_object_register(struct drm_device *dev, | ||
42 | struct drm_mode_object *obj); | ||
38 | int drm_mode_object_get(struct drm_device *dev, | 43 | int drm_mode_object_get(struct drm_device *dev, |
39 | struct drm_mode_object *obj, uint32_t obj_type); | 44 | struct drm_mode_object *obj, uint32_t obj_type); |
45 | struct drm_mode_object *__drm_mode_object_find(struct drm_device *dev, | ||
46 | uint32_t id, uint32_t type); | ||
40 | void drm_mode_object_unregister(struct drm_device *dev, | 47 | void drm_mode_object_unregister(struct drm_device *dev, |
41 | struct drm_mode_object *object); | 48 | struct drm_mode_object *object); |
49 | int drm_mode_object_get_properties(struct drm_mode_object *obj, bool atomic, | ||
50 | uint32_t __user *prop_ptr, | ||
51 | uint64_t __user *prop_values, | ||
52 | uint32_t *arg_count_props); | ||
42 | bool drm_property_change_valid_get(struct drm_property *property, | 53 | bool drm_property_change_valid_get(struct drm_property *property, |
43 | uint64_t value, | 54 | uint64_t value, |
44 | struct drm_mode_object **ref); | 55 | struct drm_mode_object **ref); |
@@ -64,18 +75,6 @@ int drm_mode_mmap_dumb_ioctl(struct drm_device *dev, | |||
64 | int drm_mode_destroy_dumb_ioctl(struct drm_device *dev, | 75 | int drm_mode_destroy_dumb_ioctl(struct drm_device *dev, |
65 | void *data, struct drm_file *file_priv); | 76 | void *data, struct drm_file *file_priv); |
66 | 77 | ||
67 | /* framebuffer IOCTLs */ | ||
68 | extern int drm_mode_addfb(struct drm_device *dev, | ||
69 | void *data, struct drm_file *file_priv); | ||
70 | extern int drm_mode_addfb2(struct drm_device *dev, | ||
71 | void *data, struct drm_file *file_priv); | ||
72 | int drm_mode_rmfb(struct drm_device *dev, | ||
73 | void *data, struct drm_file *file_priv); | ||
74 | int drm_mode_getfb(struct drm_device *dev, | ||
75 | void *data, struct drm_file *file_priv); | ||
76 | int drm_mode_dirtyfb_ioctl(struct drm_device *dev, | ||
77 | void *data, struct drm_file *file_priv); | ||
78 | |||
79 | /* IOCTLs */ | 78 | /* IOCTLs */ |
80 | int drm_mode_obj_get_properties_ioctl(struct drm_device *dev, void *data, | 79 | int drm_mode_obj_get_properties_ioctl(struct drm_device *dev, void *data, |
81 | struct drm_file *file_priv); | 80 | struct drm_file *file_priv); |
@@ -88,8 +87,6 @@ int drm_mode_getplane_res(struct drm_device *dev, void *data, | |||
88 | struct drm_file *file_priv); | 87 | struct drm_file *file_priv); |
89 | int drm_mode_getcrtc(struct drm_device *dev, | 88 | int drm_mode_getcrtc(struct drm_device *dev, |
90 | void *data, struct drm_file *file_priv); | 89 | void *data, struct drm_file *file_priv); |
91 | int drm_mode_getconnector(struct drm_device *dev, | ||
92 | void *data, struct drm_file *file_priv); | ||
93 | int drm_mode_setcrtc(struct drm_device *dev, | 90 | int drm_mode_setcrtc(struct drm_device *dev, |
94 | void *data, struct drm_file *file_priv); | 91 | void *data, struct drm_file *file_priv); |
95 | int drm_mode_getplane(struct drm_device *dev, | 92 | int drm_mode_getplane(struct drm_device *dev, |
@@ -108,8 +105,6 @@ int drm_mode_createblob_ioctl(struct drm_device *dev, | |||
108 | void *data, struct drm_file *file_priv); | 105 | void *data, struct drm_file *file_priv); |
109 | int drm_mode_destroyblob_ioctl(struct drm_device *dev, | 106 | int drm_mode_destroyblob_ioctl(struct drm_device *dev, |
110 | void *data, struct drm_file *file_priv); | 107 | void *data, struct drm_file *file_priv); |
111 | int drm_mode_connector_property_set_ioctl(struct drm_device *dev, | ||
112 | void *data, struct drm_file *file_priv); | ||
113 | int drm_mode_getencoder(struct drm_device *dev, | 108 | int drm_mode_getencoder(struct drm_device *dev, |
114 | void *data, struct drm_file *file_priv); | 109 | void *data, struct drm_file *file_priv); |
115 | int drm_mode_gamma_get_ioctl(struct drm_device *dev, | 110 | int drm_mode_gamma_get_ioctl(struct drm_device *dev, |
@@ -120,6 +115,41 @@ int drm_mode_gamma_set_ioctl(struct drm_device *dev, | |||
120 | int drm_mode_page_flip_ioctl(struct drm_device *dev, | 115 | int drm_mode_page_flip_ioctl(struct drm_device *dev, |
121 | void *data, struct drm_file *file_priv); | 116 | void *data, struct drm_file *file_priv); |
122 | 117 | ||
118 | /* drm_connector.c */ | ||
119 | void drm_connector_ida_init(void); | ||
120 | void drm_connector_ida_destroy(void); | ||
121 | void drm_connector_unregister_all(struct drm_device *dev); | ||
122 | int drm_connector_register_all(struct drm_device *dev); | ||
123 | int drm_mode_connector_set_obj_prop(struct drm_mode_object *obj, | ||
124 | struct drm_property *property, | ||
125 | uint64_t value); | ||
126 | int drm_connector_create_standard_properties(struct drm_device *dev); | ||
127 | |||
128 | /* IOCTL */ | ||
129 | int drm_mode_connector_property_set_ioctl(struct drm_device *dev, | ||
130 | void *data, struct drm_file *file_priv); | ||
131 | int drm_mode_getconnector(struct drm_device *dev, | ||
132 | void *data, struct drm_file *file_priv); | ||
133 | |||
134 | /* drm_framebuffer.c */ | ||
135 | struct drm_framebuffer * | ||
136 | drm_internal_framebuffer_create(struct drm_device *dev, | ||
137 | const struct drm_mode_fb_cmd2 *r, | ||
138 | struct drm_file *file_priv); | ||
139 | void drm_framebuffer_free(struct kref *kref); | ||
140 | |||
141 | /* IOCTL */ | ||
142 | int drm_mode_addfb(struct drm_device *dev, | ||
143 | void *data, struct drm_file *file_priv); | ||
144 | int drm_mode_addfb2(struct drm_device *dev, | ||
145 | void *data, struct drm_file *file_priv); | ||
146 | int drm_mode_rmfb(struct drm_device *dev, | ||
147 | void *data, struct drm_file *file_priv); | ||
148 | int drm_mode_getfb(struct drm_device *dev, | ||
149 | void *data, struct drm_file *file_priv); | ||
150 | int drm_mode_dirtyfb_ioctl(struct drm_device *dev, | ||
151 | void *data, struct drm_file *file_priv); | ||
152 | |||
123 | /* drm_atomic.c */ | 153 | /* drm_atomic.c */ |
124 | int drm_atomic_get_property(struct drm_mode_object *obj, | 154 | int drm_atomic_get_property(struct drm_mode_object *obj, |
125 | struct drm_property *property, uint64_t *val); | 155 | struct drm_property *property, uint64_t *val); |
@@ -130,5 +160,5 @@ int drm_modeset_register_all(struct drm_device *dev); | |||
130 | void drm_modeset_unregister_all(struct drm_device *dev); | 160 | void drm_modeset_unregister_all(struct drm_device *dev); |
131 | 161 | ||
132 | /* drm_blend.c */ | 162 | /* drm_blend.c */ |
133 | int drm_atomic_helper_normalize_zpos(struct drm_device *dev, | 163 | int drm_atomic_normalize_zpos(struct drm_device *dev, |
134 | struct drm_atomic_state *state); | 164 | struct drm_atomic_state *state); |
diff --git a/drivers/gpu/drm/drm_dp_aux_dev.c b/drivers/gpu/drm/drm_dp_aux_dev.c index 734f86a345f6..ec1ed94b2390 100644 --- a/drivers/gpu/drm/drm_dp_aux_dev.c +++ b/drivers/gpu/drm/drm_dp_aux_dev.c | |||
@@ -36,6 +36,8 @@ | |||
36 | #include <drm/drm_crtc.h> | 36 | #include <drm/drm_crtc.h> |
37 | #include <drm/drmP.h> | 37 | #include <drm/drmP.h> |
38 | 38 | ||
39 | #include "drm_crtc_helper_internal.h" | ||
40 | |||
39 | struct drm_dp_aux_dev { | 41 | struct drm_dp_aux_dev { |
40 | unsigned index; | 42 | unsigned index; |
41 | struct drm_dp_aux *aux; | 43 | struct drm_dp_aux *aux; |
@@ -283,12 +285,7 @@ static int auxdev_wait_atomic_t(atomic_t *p) | |||
283 | schedule(); | 285 | schedule(); |
284 | return 0; | 286 | return 0; |
285 | } | 287 | } |
286 | /** | 288 | |
287 | * drm_dp_aux_unregister_devnode() - unregister a devnode for this aux channel | ||
288 | * @aux: DisplayPort AUX channel | ||
289 | * | ||
290 | * Returns 0 on success or a negative error code on failure. | ||
291 | */ | ||
292 | void drm_dp_aux_unregister_devnode(struct drm_dp_aux *aux) | 289 | void drm_dp_aux_unregister_devnode(struct drm_dp_aux *aux) |
293 | { | 290 | { |
294 | struct drm_dp_aux_dev *aux_dev; | 291 | struct drm_dp_aux_dev *aux_dev; |
@@ -314,14 +311,7 @@ void drm_dp_aux_unregister_devnode(struct drm_dp_aux *aux) | |||
314 | DRM_DEBUG("drm_dp_aux_dev: aux [%s] unregistering\n", aux->name); | 311 | DRM_DEBUG("drm_dp_aux_dev: aux [%s] unregistering\n", aux->name); |
315 | kref_put(&aux_dev->refcount, release_drm_dp_aux_dev); | 312 | kref_put(&aux_dev->refcount, release_drm_dp_aux_dev); |
316 | } | 313 | } |
317 | EXPORT_SYMBOL(drm_dp_aux_unregister_devnode); | ||
318 | 314 | ||
319 | /** | ||
320 | * drm_dp_aux_register_devnode() - register a devnode for this aux channel | ||
321 | * @aux: DisplayPort AUX channel | ||
322 | * | ||
323 | * Returns 0 on success or a negative error code on failure. | ||
324 | */ | ||
325 | int drm_dp_aux_register_devnode(struct drm_dp_aux *aux) | 315 | int drm_dp_aux_register_devnode(struct drm_dp_aux *aux) |
326 | { | 316 | { |
327 | struct drm_dp_aux_dev *aux_dev; | 317 | struct drm_dp_aux_dev *aux_dev; |
@@ -347,7 +337,6 @@ error: | |||
347 | drm_dp_aux_unregister_devnode(aux); | 337 | drm_dp_aux_unregister_devnode(aux); |
348 | return res; | 338 | return res; |
349 | } | 339 | } |
350 | EXPORT_SYMBOL(drm_dp_aux_register_devnode); | ||
351 | 340 | ||
352 | int drm_dp_aux_dev_init(void) | 341 | int drm_dp_aux_dev_init(void) |
353 | { | 342 | { |
@@ -369,11 +358,9 @@ out: | |||
369 | class_destroy(drm_dp_aux_dev_class); | 358 | class_destroy(drm_dp_aux_dev_class); |
370 | return res; | 359 | return res; |
371 | } | 360 | } |
372 | EXPORT_SYMBOL(drm_dp_aux_dev_init); | ||
373 | 361 | ||
374 | void drm_dp_aux_dev_exit(void) | 362 | void drm_dp_aux_dev_exit(void) |
375 | { | 363 | { |
376 | unregister_chrdev(drm_dev_major, "aux"); | 364 | unregister_chrdev(drm_dev_major, "aux"); |
377 | class_destroy(drm_dp_aux_dev_class); | 365 | class_destroy(drm_dp_aux_dev_class); |
378 | } | 366 | } |
379 | EXPORT_SYMBOL(drm_dp_aux_dev_exit); | ||
diff --git a/drivers/gpu/drm/drm_dp_helper.c b/drivers/gpu/drm/drm_dp_helper.c index 5d20255f3db3..031c4d335b08 100644 --- a/drivers/gpu/drm/drm_dp_helper.c +++ b/drivers/gpu/drm/drm_dp_helper.c | |||
@@ -28,9 +28,10 @@ | |||
28 | #include <linux/sched.h> | 28 | #include <linux/sched.h> |
29 | #include <linux/i2c.h> | 29 | #include <linux/i2c.h> |
30 | #include <drm/drm_dp_helper.h> | 30 | #include <drm/drm_dp_helper.h> |
31 | #include <drm/drm_dp_aux_dev.h> | ||
32 | #include <drm/drmP.h> | 31 | #include <drm/drmP.h> |
33 | 32 | ||
33 | #include "drm_crtc_helper_internal.h" | ||
34 | |||
34 | /** | 35 | /** |
35 | * DOC: dp helpers | 36 | * DOC: dp helpers |
36 | * | 37 | * |
diff --git a/drivers/gpu/drm/drm_drv.c b/drivers/gpu/drm/drm_drv.c index 57ce9734e0c6..acf6a5f38920 100644 --- a/drivers/gpu/drm/drm_drv.c +++ b/drivers/gpu/drm/drm_drv.c | |||
@@ -63,37 +63,51 @@ static struct idr drm_minors_idr; | |||
63 | 63 | ||
64 | static struct dentry *drm_debugfs_root; | 64 | static struct dentry *drm_debugfs_root; |
65 | 65 | ||
66 | void drm_err(const char *format, ...) | 66 | #define DRM_PRINTK_FMT "[" DRM_NAME ":%s]%s %pV" |
67 | |||
68 | void drm_dev_printk(const struct device *dev, const char *level, | ||
69 | unsigned int category, const char *function_name, | ||
70 | const char *prefix, const char *format, ...) | ||
67 | { | 71 | { |
68 | struct va_format vaf; | 72 | struct va_format vaf; |
69 | va_list args; | 73 | va_list args; |
70 | 74 | ||
71 | va_start(args, format); | 75 | if (category != DRM_UT_NONE && !(drm_debug & category)) |
76 | return; | ||
72 | 77 | ||
78 | va_start(args, format); | ||
73 | vaf.fmt = format; | 79 | vaf.fmt = format; |
74 | vaf.va = &args; | 80 | vaf.va = &args; |
75 | 81 | ||
76 | printk(KERN_ERR "[" DRM_NAME ":%ps] *ERROR* %pV", | 82 | if (dev) |
77 | __builtin_return_address(0), &vaf); | 83 | dev_printk(level, dev, DRM_PRINTK_FMT, function_name, prefix, |
84 | &vaf); | ||
85 | else | ||
86 | printk("%s" DRM_PRINTK_FMT, level, function_name, prefix, &vaf); | ||
78 | 87 | ||
79 | va_end(args); | 88 | va_end(args); |
80 | } | 89 | } |
81 | EXPORT_SYMBOL(drm_err); | 90 | EXPORT_SYMBOL(drm_dev_printk); |
82 | 91 | ||
83 | void drm_ut_debug_printk(const char *function_name, const char *format, ...) | 92 | void drm_printk(const char *level, unsigned int category, |
93 | const char *function_name, const char *prefix, | ||
94 | const char *format, ...) | ||
84 | { | 95 | { |
85 | struct va_format vaf; | 96 | struct va_format vaf; |
86 | va_list args; | 97 | va_list args; |
87 | 98 | ||
99 | if (category != DRM_UT_NONE && !(drm_debug & category)) | ||
100 | return; | ||
101 | |||
88 | va_start(args, format); | 102 | va_start(args, format); |
89 | vaf.fmt = format; | 103 | vaf.fmt = format; |
90 | vaf.va = &args; | 104 | vaf.va = &args; |
91 | 105 | ||
92 | printk(KERN_DEBUG "[" DRM_NAME ":%s] %pV", function_name, &vaf); | 106 | printk("%s" DRM_PRINTK_FMT, level, function_name, prefix, &vaf); |
93 | 107 | ||
94 | va_end(args); | 108 | va_end(args); |
95 | } | 109 | } |
96 | EXPORT_SYMBOL(drm_ut_debug_printk); | 110 | EXPORT_SYMBOL(drm_printk); |
97 | 111 | ||
98 | /* | 112 | /* |
99 | * DRM Minors | 113 | * DRM Minors |
diff --git a/drivers/gpu/drm/drm_edid.c b/drivers/gpu/drm/drm_edid.c index 637a0aa4d3a0..50541324a4ab 100644 --- a/drivers/gpu/drm/drm_edid.c +++ b/drivers/gpu/drm/drm_edid.c | |||
@@ -991,7 +991,7 @@ static const struct drm_display_mode edid_cea_modes[] = { | |||
991 | .vrefresh = 120, .picture_aspect_ratio = HDMI_PICTURE_ASPECT_16_9, }, | 991 | .vrefresh = 120, .picture_aspect_ratio = HDMI_PICTURE_ASPECT_16_9, }, |
992 | /* 64 - 1920x1080@100Hz */ | 992 | /* 64 - 1920x1080@100Hz */ |
993 | { DRM_MODE("1920x1080", DRM_MODE_TYPE_DRIVER, 297000, 1920, 2448, | 993 | { DRM_MODE("1920x1080", DRM_MODE_TYPE_DRIVER, 297000, 1920, 2448, |
994 | 2492, 2640, 0, 1080, 1084, 1094, 1125, 0, | 994 | 2492, 2640, 0, 1080, 1084, 1089, 1125, 0, |
995 | DRM_MODE_FLAG_PHSYNC | DRM_MODE_FLAG_PVSYNC), | 995 | DRM_MODE_FLAG_PHSYNC | DRM_MODE_FLAG_PVSYNC), |
996 | .vrefresh = 100, .picture_aspect_ratio = HDMI_PICTURE_ASPECT_16_9, }, | 996 | .vrefresh = 100, .picture_aspect_ratio = HDMI_PICTURE_ASPECT_16_9, }, |
997 | }; | 997 | }; |
@@ -3721,14 +3721,7 @@ bool drm_rgb_quant_range_selectable(struct edid *edid) | |||
3721 | } | 3721 | } |
3722 | EXPORT_SYMBOL(drm_rgb_quant_range_selectable); | 3722 | EXPORT_SYMBOL(drm_rgb_quant_range_selectable); |
3723 | 3723 | ||
3724 | /** | 3724 | /* |
3725 | * drm_assign_hdmi_deep_color_info - detect whether monitor supports | ||
3726 | * hdmi deep color modes and update drm_display_info if so. | ||
3727 | * @edid: monitor EDID information | ||
3728 | * @info: Updated with maximum supported deep color bpc and color format | ||
3729 | * if deep color supported. | ||
3730 | * @connector: DRM connector, used only for debug output | ||
3731 | * | ||
3732 | * Parse the CEA extension according to CEA-861-B. | 3725 | * Parse the CEA extension according to CEA-861-B. |
3733 | * Return true if HDMI deep color supported, false if not or unknown. | 3726 | * Return true if HDMI deep color supported, false if not or unknown. |
3734 | */ | 3727 | */ |
@@ -3822,16 +3815,6 @@ static bool drm_assign_hdmi_deep_color_info(struct edid *edid, | |||
3822 | return false; | 3815 | return false; |
3823 | } | 3816 | } |
3824 | 3817 | ||
3825 | /** | ||
3826 | * drm_add_display_info - pull display info out if present | ||
3827 | * @edid: EDID data | ||
3828 | * @info: display info (attached to connector) | ||
3829 | * @connector: connector whose edid is used to build display info | ||
3830 | * | ||
3831 | * Grab any available display info and stuff it into the drm_display_info | ||
3832 | * structure that's part of the connector. Useful for tracking bpp and | ||
3833 | * color spaces. | ||
3834 | */ | ||
3835 | static void drm_add_display_info(struct edid *edid, | 3818 | static void drm_add_display_info(struct edid *edid, |
3836 | struct drm_display_info *info, | 3819 | struct drm_display_info *info, |
3837 | struct drm_connector *connector) | 3820 | struct drm_connector *connector) |
@@ -4052,7 +4035,9 @@ static int add_displayid_detailed_modes(struct drm_connector *connector, | |||
4052 | * @connector: connector we're probing | 4035 | * @connector: connector we're probing |
4053 | * @edid: EDID data | 4036 | * @edid: EDID data |
4054 | * | 4037 | * |
4055 | * Add the specified modes to the connector's mode list. | 4038 | * Add the specified modes to the connector's mode list. Also fills out the |
4039 | * &drm_display_info structure in @connector with any information which can be | ||
4040 | * derived from the edid. | ||
4056 | * | 4041 | * |
4057 | * Return: The number of modes added or 0 if we couldn't find any. | 4042 | * Return: The number of modes added or 0 if we couldn't find any. |
4058 | */ | 4043 | */ |
diff --git a/drivers/gpu/drm/drm_fb_helper.c b/drivers/gpu/drm/drm_fb_helper.c index aed79d31930c..c4d350086def 100644 --- a/drivers/gpu/drm/drm_fb_helper.c +++ b/drivers/gpu/drm/drm_fb_helper.c | |||
@@ -29,6 +29,7 @@ | |||
29 | */ | 29 | */ |
30 | #define pr_fmt(fmt) KBUILD_MODNAME ": " fmt | 30 | #define pr_fmt(fmt) KBUILD_MODNAME ": " fmt |
31 | 31 | ||
32 | #include <linux/console.h> | ||
32 | #include <linux/kernel.h> | 33 | #include <linux/kernel.h> |
33 | #include <linux/sysrq.h> | 34 | #include <linux/sysrq.h> |
34 | #include <linux/slab.h> | 35 | #include <linux/slab.h> |
@@ -617,6 +618,16 @@ static void drm_fb_helper_crtc_free(struct drm_fb_helper *helper) | |||
617 | kfree(helper->crtc_info); | 618 | kfree(helper->crtc_info); |
618 | } | 619 | } |
619 | 620 | ||
621 | static void drm_fb_helper_resume_worker(struct work_struct *work) | ||
622 | { | ||
623 | struct drm_fb_helper *helper = container_of(work, struct drm_fb_helper, | ||
624 | resume_work); | ||
625 | |||
626 | console_lock(); | ||
627 | fb_set_suspend(helper->fbdev, 0); | ||
628 | console_unlock(); | ||
629 | } | ||
630 | |||
620 | static void drm_fb_helper_dirty_work(struct work_struct *work) | 631 | static void drm_fb_helper_dirty_work(struct work_struct *work) |
621 | { | 632 | { |
622 | struct drm_fb_helper *helper = container_of(work, struct drm_fb_helper, | 633 | struct drm_fb_helper *helper = container_of(work, struct drm_fb_helper, |
@@ -648,6 +659,7 @@ void drm_fb_helper_prepare(struct drm_device *dev, struct drm_fb_helper *helper, | |||
648 | { | 659 | { |
649 | INIT_LIST_HEAD(&helper->kernel_fb_list); | 660 | INIT_LIST_HEAD(&helper->kernel_fb_list); |
650 | spin_lock_init(&helper->dirty_lock); | 661 | spin_lock_init(&helper->dirty_lock); |
662 | INIT_WORK(&helper->resume_work, drm_fb_helper_resume_worker); | ||
651 | INIT_WORK(&helper->dirty_work, drm_fb_helper_dirty_work); | 663 | INIT_WORK(&helper->dirty_work, drm_fb_helper_dirty_work); |
652 | helper->dirty_clip.x1 = helper->dirty_clip.y1 = ~0; | 664 | helper->dirty_clip.x1 = helper->dirty_clip.y1 = ~0; |
653 | helper->funcs = funcs; | 665 | helper->funcs = funcs; |
@@ -1023,17 +1035,65 @@ EXPORT_SYMBOL(drm_fb_helper_cfb_imageblit); | |||
1023 | /** | 1035 | /** |
1024 | * drm_fb_helper_set_suspend - wrapper around fb_set_suspend | 1036 | * drm_fb_helper_set_suspend - wrapper around fb_set_suspend |
1025 | * @fb_helper: driver-allocated fbdev helper | 1037 | * @fb_helper: driver-allocated fbdev helper |
1026 | * @state: desired state, zero to resume, non-zero to suspend | 1038 | * @suspend: whether to suspend or resume |
1027 | * | 1039 | * |
1028 | * A wrapper around fb_set_suspend implemented by fbdev core | 1040 | * A wrapper around fb_set_suspend implemented by fbdev core. |
1041 | * Use drm_fb_helper_set_suspend_unlocked() if you don't need to take | ||
1042 | * the lock yourself | ||
1029 | */ | 1043 | */ |
1030 | void drm_fb_helper_set_suspend(struct drm_fb_helper *fb_helper, int state) | 1044 | void drm_fb_helper_set_suspend(struct drm_fb_helper *fb_helper, bool suspend) |
1031 | { | 1045 | { |
1032 | if (fb_helper && fb_helper->fbdev) | 1046 | if (fb_helper && fb_helper->fbdev) |
1033 | fb_set_suspend(fb_helper->fbdev, state); | 1047 | fb_set_suspend(fb_helper->fbdev, suspend); |
1034 | } | 1048 | } |
1035 | EXPORT_SYMBOL(drm_fb_helper_set_suspend); | 1049 | EXPORT_SYMBOL(drm_fb_helper_set_suspend); |
1036 | 1050 | ||
1051 | /** | ||
1052 | * drm_fb_helper_set_suspend_unlocked - wrapper around fb_set_suspend that also | ||
1053 | * takes the console lock | ||
1054 | * @fb_helper: driver-allocated fbdev helper | ||
1055 | * @suspend: whether to suspend or resume | ||
1056 | * | ||
1057 | * A wrapper around fb_set_suspend() that takes the console lock. If the lock | ||
1058 | * isn't available on resume, a worker is tasked with waiting for the lock | ||
1059 | * to become available. The console lock can be pretty contented on resume | ||
1060 | * due to all the printk activity. | ||
1061 | * | ||
1062 | * This function can be called multiple times with the same state since | ||
1063 | * &fb_info->state is checked to see if fbdev is running or not before locking. | ||
1064 | * | ||
1065 | * Use drm_fb_helper_set_suspend() if you need to take the lock yourself. | ||
1066 | */ | ||
1067 | void drm_fb_helper_set_suspend_unlocked(struct drm_fb_helper *fb_helper, | ||
1068 | bool suspend) | ||
1069 | { | ||
1070 | if (!fb_helper || !fb_helper->fbdev) | ||
1071 | return; | ||
1072 | |||
1073 | /* make sure there's no pending/ongoing resume */ | ||
1074 | flush_work(&fb_helper->resume_work); | ||
1075 | |||
1076 | if (suspend) { | ||
1077 | if (fb_helper->fbdev->state != FBINFO_STATE_RUNNING) | ||
1078 | return; | ||
1079 | |||
1080 | console_lock(); | ||
1081 | |||
1082 | } else { | ||
1083 | if (fb_helper->fbdev->state == FBINFO_STATE_RUNNING) | ||
1084 | return; | ||
1085 | |||
1086 | if (!console_trylock()) { | ||
1087 | schedule_work(&fb_helper->resume_work); | ||
1088 | return; | ||
1089 | } | ||
1090 | } | ||
1091 | |||
1092 | fb_set_suspend(fb_helper->fbdev, suspend); | ||
1093 | console_unlock(); | ||
1094 | } | ||
1095 | EXPORT_SYMBOL(drm_fb_helper_set_suspend_unlocked); | ||
1096 | |||
1037 | static int setcolreg(struct drm_crtc *crtc, u16 red, u16 green, | 1097 | static int setcolreg(struct drm_crtc *crtc, u16 red, u16 green, |
1038 | u16 blue, u16 regno, struct fb_info *info) | 1098 | u16 blue, u16 regno, struct fb_info *info) |
1039 | { | 1099 | { |
@@ -2193,7 +2253,7 @@ EXPORT_SYMBOL(drm_fb_helper_initial_config); | |||
2193 | * @fb_helper: the drm_fb_helper | 2253 | * @fb_helper: the drm_fb_helper |
2194 | * | 2254 | * |
2195 | * Scan the connectors attached to the fb_helper and try to put together a | 2255 | * Scan the connectors attached to the fb_helper and try to put together a |
2196 | * setup after *notification of a change in output configuration. | 2256 | * setup after notification of a change in output configuration. |
2197 | * | 2257 | * |
2198 | * Called at runtime, takes the mode config locks to be able to check/change the | 2258 | * Called at runtime, takes the mode config locks to be able to check/change the |
2199 | * modeset configuration. Must be run from process context (which usually means | 2259 | * modeset configuration. Must be run from process context (which usually means |
diff --git a/drivers/gpu/drm/drm_fourcc.c b/drivers/gpu/drm/drm_fourcc.c index 0645c85d5f95..c81546c15c93 100644 --- a/drivers/gpu/drm/drm_fourcc.c +++ b/drivers/gpu/drm/drm_fourcc.c | |||
@@ -39,16 +39,14 @@ static char printable_char(int c) | |||
39 | * drm_get_format_name - return a string for drm fourcc format | 39 | * drm_get_format_name - return a string for drm fourcc format |
40 | * @format: format to compute name of | 40 | * @format: format to compute name of |
41 | * | 41 | * |
42 | * Note that the buffer used by this function is globally shared and owned by | 42 | * Note that the buffer returned by this function is owned by the caller |
43 | * the function itself. | 43 | * and will need to be freed using kfree(). |
44 | * | ||
45 | * FIXME: This isn't really multithreading safe. | ||
46 | */ | 44 | */ |
47 | const char *drm_get_format_name(uint32_t format) | 45 | char *drm_get_format_name(uint32_t format) |
48 | { | 46 | { |
49 | static char buf[32]; | 47 | char *buf = kmalloc(32, GFP_KERNEL); |
50 | 48 | ||
51 | snprintf(buf, sizeof(buf), | 49 | snprintf(buf, 32, |
52 | "%c%c%c%c %s-endian (0x%08x)", | 50 | "%c%c%c%c %s-endian (0x%08x)", |
53 | printable_char(format & 0xff), | 51 | printable_char(format & 0xff), |
54 | printable_char((format >> 8) & 0xff), | 52 | printable_char((format >> 8) & 0xff), |
@@ -73,6 +71,8 @@ EXPORT_SYMBOL(drm_get_format_name); | |||
73 | void drm_fb_get_bpp_depth(uint32_t format, unsigned int *depth, | 71 | void drm_fb_get_bpp_depth(uint32_t format, unsigned int *depth, |
74 | int *bpp) | 72 | int *bpp) |
75 | { | 73 | { |
74 | char *format_name; | ||
75 | |||
76 | switch (format) { | 76 | switch (format) { |
77 | case DRM_FORMAT_C8: | 77 | case DRM_FORMAT_C8: |
78 | case DRM_FORMAT_RGB332: | 78 | case DRM_FORMAT_RGB332: |
@@ -127,8 +127,9 @@ void drm_fb_get_bpp_depth(uint32_t format, unsigned int *depth, | |||
127 | *bpp = 32; | 127 | *bpp = 32; |
128 | break; | 128 | break; |
129 | default: | 129 | default: |
130 | DRM_DEBUG_KMS("unsupported pixel format %s\n", | 130 | format_name = drm_get_format_name(format); |
131 | drm_get_format_name(format)); | 131 | DRM_DEBUG_KMS("unsupported pixel format %s\n", format_name); |
132 | kfree(format_name); | ||
132 | *depth = 0; | 133 | *depth = 0; |
133 | *bpp = 0; | 134 | *bpp = 0; |
134 | break; | 135 | break; |
diff --git a/drivers/gpu/drm/drm_framebuffer.c b/drivers/gpu/drm/drm_framebuffer.c new file mode 100644 index 000000000000..30dc01e6eb5d --- /dev/null +++ b/drivers/gpu/drm/drm_framebuffer.c | |||
@@ -0,0 +1,831 @@ | |||
1 | /* | ||
2 | * Copyright (c) 2016 Intel Corporation | ||
3 | * | ||
4 | * Permission to use, copy, modify, distribute, and sell this software and its | ||
5 | * documentation for any purpose is hereby granted without fee, provided that | ||
6 | * the above copyright notice appear in all copies and that both that copyright | ||
7 | * notice and this permission notice appear in supporting documentation, and | ||
8 | * that the name of the copyright holders not be used in advertising or | ||
9 | * publicity pertaining to distribution of the software without specific, | ||
10 | * written prior permission. The copyright holders make no representations | ||
11 | * about the suitability of this software for any purpose. It is provided "as | ||
12 | * is" without express or implied warranty. | ||
13 | * | ||
14 | * THE COPYRIGHT HOLDERS DISCLAIM ALL WARRANTIES WITH REGARD TO THIS SOFTWARE, | ||
15 | * INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS, IN NO | ||
16 | * EVENT SHALL THE COPYRIGHT HOLDERS BE LIABLE FOR ANY SPECIAL, INDIRECT OR | ||
17 | * CONSEQUENTIAL DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM LOSS OF USE, | ||
18 | * DATA OR PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER | ||
19 | * TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR PERFORMANCE | ||
20 | * OF THIS SOFTWARE. | ||
21 | */ | ||
22 | |||
23 | #include <linux/export.h> | ||
24 | #include <drm/drmP.h> | ||
25 | #include <drm/drm_auth.h> | ||
26 | #include <drm/drm_framebuffer.h> | ||
27 | |||
28 | #include "drm_crtc_internal.h" | ||
29 | |||
30 | /** | ||
31 | * DOC: overview | ||
32 | * | ||
33 | * Frame buffers are abstract memory objects that provide a source of pixels to | ||
34 | * scanout to a CRTC. Applications explicitly request the creation of frame | ||
35 | * buffers through the DRM_IOCTL_MODE_ADDFB(2) ioctls and receive an opaque | ||
36 | * handle that can be passed to the KMS CRTC control, plane configuration and | ||
37 | * page flip functions. | ||
38 | * | ||
39 | * Frame buffers rely on the underlying memory manager for allocating backing | ||
40 | * storage. When creating a frame buffer applications pass a memory handle | ||
41 | * (or a list of memory handles for multi-planar formats) through the | ||
42 | * struct &drm_mode_fb_cmd2 argument. For drivers using GEM as their userspace | ||
43 | * buffer management interface this would be a GEM handle. Drivers are however | ||
44 | * free to use their own backing storage object handles, e.g. vmwgfx directly | ||
45 | * exposes special TTM handles to userspace and so expects TTM handles in the | ||
46 | * create ioctl and not GEM handles. | ||
47 | * | ||
48 | * Framebuffers are tracked with struct &drm_framebuffer. They are published | ||
49 | * using drm_framebuffer_init() - after calling that function userspace can use | ||
50 | * and access the framebuffer object. The helper function | ||
51 | * drm_helper_mode_fill_fb_struct() can be used to pre-fill the required | ||
52 | * metadata fields. | ||
53 | * | ||
54 | * The lifetime of a drm framebuffer is controlled with a reference count, | ||
55 | * drivers can grab additional references with drm_framebuffer_reference() and | ||
56 | * drop them again with drm_framebuffer_unreference(). For driver-private | ||
57 | * framebuffers for which the last reference is never dropped (e.g. for the | ||
58 | * fbdev framebuffer when the struct struct &drm_framebuffer is embedded into | ||
59 | * the fbdev helper struct) drivers can manually clean up a framebuffer at | ||
60 | * module unload time with drm_framebuffer_unregister_private(). But doing this | ||
61 | * is not recommended, and it's better to have a normal free-standing struct | ||
62 | * &drm_framebuffer. | ||
63 | */ | ||
64 | |||
65 | /** | ||
66 | * drm_mode_addfb - add an FB to the graphics configuration | ||
67 | * @dev: drm device for the ioctl | ||
68 | * @data: data pointer for the ioctl | ||
69 | * @file_priv: drm file for the ioctl call | ||
70 | * | ||
71 | * Add a new FB to the specified CRTC, given a user request. This is the | ||
72 | * original addfb ioctl which only supported RGB formats. | ||
73 | * | ||
74 | * Called by the user via ioctl. | ||
75 | * | ||
76 | * Returns: | ||
77 | * Zero on success, negative errno on failure. | ||
78 | */ | ||
79 | int drm_mode_addfb(struct drm_device *dev, | ||
80 | void *data, struct drm_file *file_priv) | ||
81 | { | ||
82 | struct drm_mode_fb_cmd *or = data; | ||
83 | struct drm_mode_fb_cmd2 r = {}; | ||
84 | int ret; | ||
85 | |||
86 | /* convert to new format and call new ioctl */ | ||
87 | r.fb_id = or->fb_id; | ||
88 | r.width = or->width; | ||
89 | r.height = or->height; | ||
90 | r.pitches[0] = or->pitch; | ||
91 | r.pixel_format = drm_mode_legacy_fb_format(or->bpp, or->depth); | ||
92 | r.handles[0] = or->handle; | ||
93 | |||
94 | ret = drm_mode_addfb2(dev, &r, file_priv); | ||
95 | if (ret) | ||
96 | return ret; | ||
97 | |||
98 | or->fb_id = r.fb_id; | ||
99 | |||
100 | return 0; | ||
101 | } | ||
102 | |||
103 | static int format_check(const struct drm_mode_fb_cmd2 *r) | ||
104 | { | ||
105 | uint32_t format = r->pixel_format & ~DRM_FORMAT_BIG_ENDIAN; | ||
106 | char *format_name; | ||
107 | |||
108 | switch (format) { | ||
109 | case DRM_FORMAT_C8: | ||
110 | case DRM_FORMAT_RGB332: | ||
111 | case DRM_FORMAT_BGR233: | ||
112 | case DRM_FORMAT_XRGB4444: | ||
113 | case DRM_FORMAT_XBGR4444: | ||
114 | case DRM_FORMAT_RGBX4444: | ||
115 | case DRM_FORMAT_BGRX4444: | ||
116 | case DRM_FORMAT_ARGB4444: | ||
117 | case DRM_FORMAT_ABGR4444: | ||
118 | case DRM_FORMAT_RGBA4444: | ||
119 | case DRM_FORMAT_BGRA4444: | ||
120 | case DRM_FORMAT_XRGB1555: | ||
121 | case DRM_FORMAT_XBGR1555: | ||
122 | case DRM_FORMAT_RGBX5551: | ||
123 | case DRM_FORMAT_BGRX5551: | ||
124 | case DRM_FORMAT_ARGB1555: | ||
125 | case DRM_FORMAT_ABGR1555: | ||
126 | case DRM_FORMAT_RGBA5551: | ||
127 | case DRM_FORMAT_BGRA5551: | ||
128 | case DRM_FORMAT_RGB565: | ||
129 | case DRM_FORMAT_BGR565: | ||
130 | case DRM_FORMAT_RGB888: | ||
131 | case DRM_FORMAT_BGR888: | ||
132 | case DRM_FORMAT_XRGB8888: | ||
133 | case DRM_FORMAT_XBGR8888: | ||
134 | case DRM_FORMAT_RGBX8888: | ||
135 | case DRM_FORMAT_BGRX8888: | ||
136 | case DRM_FORMAT_ARGB8888: | ||
137 | case DRM_FORMAT_ABGR8888: | ||
138 | case DRM_FORMAT_RGBA8888: | ||
139 | case DRM_FORMAT_BGRA8888: | ||
140 | case DRM_FORMAT_XRGB2101010: | ||
141 | case DRM_FORMAT_XBGR2101010: | ||
142 | case DRM_FORMAT_RGBX1010102: | ||
143 | case DRM_FORMAT_BGRX1010102: | ||
144 | case DRM_FORMAT_ARGB2101010: | ||
145 | case DRM_FORMAT_ABGR2101010: | ||
146 | case DRM_FORMAT_RGBA1010102: | ||
147 | case DRM_FORMAT_BGRA1010102: | ||
148 | case DRM_FORMAT_YUYV: | ||
149 | case DRM_FORMAT_YVYU: | ||
150 | case DRM_FORMAT_UYVY: | ||
151 | case DRM_FORMAT_VYUY: | ||
152 | case DRM_FORMAT_AYUV: | ||
153 | case DRM_FORMAT_NV12: | ||
154 | case DRM_FORMAT_NV21: | ||
155 | case DRM_FORMAT_NV16: | ||
156 | case DRM_FORMAT_NV61: | ||
157 | case DRM_FORMAT_NV24: | ||
158 | case DRM_FORMAT_NV42: | ||
159 | case DRM_FORMAT_YUV410: | ||
160 | case DRM_FORMAT_YVU410: | ||
161 | case DRM_FORMAT_YUV411: | ||
162 | case DRM_FORMAT_YVU411: | ||
163 | case DRM_FORMAT_YUV420: | ||
164 | case DRM_FORMAT_YVU420: | ||
165 | case DRM_FORMAT_YUV422: | ||
166 | case DRM_FORMAT_YVU422: | ||
167 | case DRM_FORMAT_YUV444: | ||
168 | case DRM_FORMAT_YVU444: | ||
169 | return 0; | ||
170 | default: | ||
171 | format_name = drm_get_format_name(r->pixel_format); | ||
172 | DRM_DEBUG_KMS("invalid pixel format %s\n", format_name); | ||
173 | kfree(format_name); | ||
174 | return -EINVAL; | ||
175 | } | ||
176 | } | ||
177 | |||
178 | static int framebuffer_check(const struct drm_mode_fb_cmd2 *r) | ||
179 | { | ||
180 | int ret, hsub, vsub, num_planes, i; | ||
181 | |||
182 | ret = format_check(r); | ||
183 | if (ret) { | ||
184 | char *format_name = drm_get_format_name(r->pixel_format); | ||
185 | DRM_DEBUG_KMS("bad framebuffer format %s\n", format_name); | ||
186 | kfree(format_name); | ||
187 | return ret; | ||
188 | } | ||
189 | |||
190 | hsub = drm_format_horz_chroma_subsampling(r->pixel_format); | ||
191 | vsub = drm_format_vert_chroma_subsampling(r->pixel_format); | ||
192 | num_planes = drm_format_num_planes(r->pixel_format); | ||
193 | |||
194 | if (r->width == 0 || r->width % hsub) { | ||
195 | DRM_DEBUG_KMS("bad framebuffer width %u\n", r->width); | ||
196 | return -EINVAL; | ||
197 | } | ||
198 | |||
199 | if (r->height == 0 || r->height % vsub) { | ||
200 | DRM_DEBUG_KMS("bad framebuffer height %u\n", r->height); | ||
201 | return -EINVAL; | ||
202 | } | ||
203 | |||
204 | for (i = 0; i < num_planes; i++) { | ||
205 | unsigned int width = r->width / (i != 0 ? hsub : 1); | ||
206 | unsigned int height = r->height / (i != 0 ? vsub : 1); | ||
207 | unsigned int cpp = drm_format_plane_cpp(r->pixel_format, i); | ||
208 | |||
209 | if (!r->handles[i]) { | ||
210 | DRM_DEBUG_KMS("no buffer object handle for plane %d\n", i); | ||
211 | return -EINVAL; | ||
212 | } | ||
213 | |||
214 | if ((uint64_t) width * cpp > UINT_MAX) | ||
215 | return -ERANGE; | ||
216 | |||
217 | if ((uint64_t) height * r->pitches[i] + r->offsets[i] > UINT_MAX) | ||
218 | return -ERANGE; | ||
219 | |||
220 | if (r->pitches[i] < width * cpp) { | ||
221 | DRM_DEBUG_KMS("bad pitch %u for plane %d\n", r->pitches[i], i); | ||
222 | return -EINVAL; | ||
223 | } | ||
224 | |||
225 | if (r->modifier[i] && !(r->flags & DRM_MODE_FB_MODIFIERS)) { | ||
226 | DRM_DEBUG_KMS("bad fb modifier %llu for plane %d\n", | ||
227 | r->modifier[i], i); | ||
228 | return -EINVAL; | ||
229 | } | ||
230 | |||
231 | /* modifier specific checks: */ | ||
232 | switch (r->modifier[i]) { | ||
233 | case DRM_FORMAT_MOD_SAMSUNG_64_32_TILE: | ||
234 | /* NOTE: the pitch restriction may be lifted later if it turns | ||
235 | * out that no hw has this restriction: | ||
236 | */ | ||
237 | if (r->pixel_format != DRM_FORMAT_NV12 || | ||
238 | width % 128 || height % 32 || | ||
239 | r->pitches[i] % 128) { | ||
240 | DRM_DEBUG_KMS("bad modifier data for plane %d\n", i); | ||
241 | return -EINVAL; | ||
242 | } | ||
243 | break; | ||
244 | |||
245 | default: | ||
246 | break; | ||
247 | } | ||
248 | } | ||
249 | |||
250 | for (i = num_planes; i < 4; i++) { | ||
251 | if (r->modifier[i]) { | ||
252 | DRM_DEBUG_KMS("non-zero modifier for unused plane %d\n", i); | ||
253 | return -EINVAL; | ||
254 | } | ||
255 | |||
256 | /* Pre-FB_MODIFIERS userspace didn't clear the structs properly. */ | ||
257 | if (!(r->flags & DRM_MODE_FB_MODIFIERS)) | ||
258 | continue; | ||
259 | |||
260 | if (r->handles[i]) { | ||
261 | DRM_DEBUG_KMS("buffer object handle for unused plane %d\n", i); | ||
262 | return -EINVAL; | ||
263 | } | ||
264 | |||
265 | if (r->pitches[i]) { | ||
266 | DRM_DEBUG_KMS("non-zero pitch for unused plane %d\n", i); | ||
267 | return -EINVAL; | ||
268 | } | ||
269 | |||
270 | if (r->offsets[i]) { | ||
271 | DRM_DEBUG_KMS("non-zero offset for unused plane %d\n", i); | ||
272 | return -EINVAL; | ||
273 | } | ||
274 | } | ||
275 | |||
276 | return 0; | ||
277 | } | ||
278 | |||
279 | struct drm_framebuffer * | ||
280 | drm_internal_framebuffer_create(struct drm_device *dev, | ||
281 | const struct drm_mode_fb_cmd2 *r, | ||
282 | struct drm_file *file_priv) | ||
283 | { | ||
284 | struct drm_mode_config *config = &dev->mode_config; | ||
285 | struct drm_framebuffer *fb; | ||
286 | int ret; | ||
287 | |||
288 | if (r->flags & ~(DRM_MODE_FB_INTERLACED | DRM_MODE_FB_MODIFIERS)) { | ||
289 | DRM_DEBUG_KMS("bad framebuffer flags 0x%08x\n", r->flags); | ||
290 | return ERR_PTR(-EINVAL); | ||
291 | } | ||
292 | |||
293 | if ((config->min_width > r->width) || (r->width > config->max_width)) { | ||
294 | DRM_DEBUG_KMS("bad framebuffer width %d, should be >= %d && <= %d\n", | ||
295 | r->width, config->min_width, config->max_width); | ||
296 | return ERR_PTR(-EINVAL); | ||
297 | } | ||
298 | if ((config->min_height > r->height) || (r->height > config->max_height)) { | ||
299 | DRM_DEBUG_KMS("bad framebuffer height %d, should be >= %d && <= %d\n", | ||
300 | r->height, config->min_height, config->max_height); | ||
301 | return ERR_PTR(-EINVAL); | ||
302 | } | ||
303 | |||
304 | if (r->flags & DRM_MODE_FB_MODIFIERS && | ||
305 | !dev->mode_config.allow_fb_modifiers) { | ||
306 | DRM_DEBUG_KMS("driver does not support fb modifiers\n"); | ||
307 | return ERR_PTR(-EINVAL); | ||
308 | } | ||
309 | |||
310 | ret = framebuffer_check(r); | ||
311 | if (ret) | ||
312 | return ERR_PTR(ret); | ||
313 | |||
314 | fb = dev->mode_config.funcs->fb_create(dev, file_priv, r); | ||
315 | if (IS_ERR(fb)) { | ||
316 | DRM_DEBUG_KMS("could not create framebuffer\n"); | ||
317 | return fb; | ||
318 | } | ||
319 | |||
320 | return fb; | ||
321 | } | ||
322 | |||
323 | /** | ||
324 | * drm_mode_addfb2 - add an FB to the graphics configuration | ||
325 | * @dev: drm device for the ioctl | ||
326 | * @data: data pointer for the ioctl | ||
327 | * @file_priv: drm file for the ioctl call | ||
328 | * | ||
329 | * Add a new FB to the specified CRTC, given a user request with format. This is | ||
330 | * the 2nd version of the addfb ioctl, which supports multi-planar framebuffers | ||
331 | * and uses fourcc codes as pixel format specifiers. | ||
332 | * | ||
333 | * Called by the user via ioctl. | ||
334 | * | ||
335 | * Returns: | ||
336 | * Zero on success, negative errno on failure. | ||
337 | */ | ||
338 | int drm_mode_addfb2(struct drm_device *dev, | ||
339 | void *data, struct drm_file *file_priv) | ||
340 | { | ||
341 | struct drm_mode_fb_cmd2 *r = data; | ||
342 | struct drm_framebuffer *fb; | ||
343 | |||
344 | if (!drm_core_check_feature(dev, DRIVER_MODESET)) | ||
345 | return -EINVAL; | ||
346 | |||
347 | fb = drm_internal_framebuffer_create(dev, r, file_priv); | ||
348 | if (IS_ERR(fb)) | ||
349 | return PTR_ERR(fb); | ||
350 | |||
351 | DRM_DEBUG_KMS("[FB:%d]\n", fb->base.id); | ||
352 | r->fb_id = fb->base.id; | ||
353 | |||
354 | /* Transfer ownership to the filp for reaping on close */ | ||
355 | mutex_lock(&file_priv->fbs_lock); | ||
356 | list_add(&fb->filp_head, &file_priv->fbs); | ||
357 | mutex_unlock(&file_priv->fbs_lock); | ||
358 | |||
359 | return 0; | ||
360 | } | ||
361 | |||
362 | struct drm_mode_rmfb_work { | ||
363 | struct work_struct work; | ||
364 | struct list_head fbs; | ||
365 | }; | ||
366 | |||
367 | static void drm_mode_rmfb_work_fn(struct work_struct *w) | ||
368 | { | ||
369 | struct drm_mode_rmfb_work *arg = container_of(w, typeof(*arg), work); | ||
370 | |||
371 | while (!list_empty(&arg->fbs)) { | ||
372 | struct drm_framebuffer *fb = | ||
373 | list_first_entry(&arg->fbs, typeof(*fb), filp_head); | ||
374 | |||
375 | list_del_init(&fb->filp_head); | ||
376 | drm_framebuffer_remove(fb); | ||
377 | } | ||
378 | } | ||
379 | |||
380 | /** | ||
381 | * drm_mode_rmfb - remove an FB from the configuration | ||
382 | * @dev: drm device for the ioctl | ||
383 | * @data: data pointer for the ioctl | ||
384 | * @file_priv: drm file for the ioctl call | ||
385 | * | ||
386 | * Remove the FB specified by the user. | ||
387 | * | ||
388 | * Called by the user via ioctl. | ||
389 | * | ||
390 | * Returns: | ||
391 | * Zero on success, negative errno on failure. | ||
392 | */ | ||
393 | int drm_mode_rmfb(struct drm_device *dev, | ||
394 | void *data, struct drm_file *file_priv) | ||
395 | { | ||
396 | struct drm_framebuffer *fb = NULL; | ||
397 | struct drm_framebuffer *fbl = NULL; | ||
398 | uint32_t *id = data; | ||
399 | int found = 0; | ||
400 | |||
401 | if (!drm_core_check_feature(dev, DRIVER_MODESET)) | ||
402 | return -EINVAL; | ||
403 | |||
404 | fb = drm_framebuffer_lookup(dev, *id); | ||
405 | if (!fb) | ||
406 | return -ENOENT; | ||
407 | |||
408 | mutex_lock(&file_priv->fbs_lock); | ||
409 | list_for_each_entry(fbl, &file_priv->fbs, filp_head) | ||
410 | if (fb == fbl) | ||
411 | found = 1; | ||
412 | if (!found) { | ||
413 | mutex_unlock(&file_priv->fbs_lock); | ||
414 | goto fail_unref; | ||
415 | } | ||
416 | |||
417 | list_del_init(&fb->filp_head); | ||
418 | mutex_unlock(&file_priv->fbs_lock); | ||
419 | |||
420 | /* drop the reference we picked up in framebuffer lookup */ | ||
421 | drm_framebuffer_unreference(fb); | ||
422 | |||
423 | /* | ||
424 | * we now own the reference that was stored in the fbs list | ||
425 | * | ||
426 | * drm_framebuffer_remove may fail with -EINTR on pending signals, | ||
427 | * so run this in a separate stack as there's no way to correctly | ||
428 | * handle this after the fb is already removed from the lookup table. | ||
429 | */ | ||
430 | if (drm_framebuffer_read_refcount(fb) > 1) { | ||
431 | struct drm_mode_rmfb_work arg; | ||
432 | |||
433 | INIT_WORK_ONSTACK(&arg.work, drm_mode_rmfb_work_fn); | ||
434 | INIT_LIST_HEAD(&arg.fbs); | ||
435 | list_add_tail(&fb->filp_head, &arg.fbs); | ||
436 | |||
437 | schedule_work(&arg.work); | ||
438 | flush_work(&arg.work); | ||
439 | destroy_work_on_stack(&arg.work); | ||
440 | } else | ||
441 | drm_framebuffer_unreference(fb); | ||
442 | |||
443 | return 0; | ||
444 | |||
445 | fail_unref: | ||
446 | drm_framebuffer_unreference(fb); | ||
447 | return -ENOENT; | ||
448 | } | ||
449 | |||
450 | /** | ||
451 | * drm_mode_getfb - get FB info | ||
452 | * @dev: drm device for the ioctl | ||
453 | * @data: data pointer for the ioctl | ||
454 | * @file_priv: drm file for the ioctl call | ||
455 | * | ||
456 | * Lookup the FB given its ID and return info about it. | ||
457 | * | ||
458 | * Called by the user via ioctl. | ||
459 | * | ||
460 | * Returns: | ||
461 | * Zero on success, negative errno on failure. | ||
462 | */ | ||
463 | int drm_mode_getfb(struct drm_device *dev, | ||
464 | void *data, struct drm_file *file_priv) | ||
465 | { | ||
466 | struct drm_mode_fb_cmd *r = data; | ||
467 | struct drm_framebuffer *fb; | ||
468 | int ret; | ||
469 | |||
470 | if (!drm_core_check_feature(dev, DRIVER_MODESET)) | ||
471 | return -EINVAL; | ||
472 | |||
473 | fb = drm_framebuffer_lookup(dev, r->fb_id); | ||
474 | if (!fb) | ||
475 | return -ENOENT; | ||
476 | |||
477 | r->height = fb->height; | ||
478 | r->width = fb->width; | ||
479 | r->depth = fb->depth; | ||
480 | r->bpp = fb->bits_per_pixel; | ||
481 | r->pitch = fb->pitches[0]; | ||
482 | if (fb->funcs->create_handle) { | ||
483 | if (drm_is_current_master(file_priv) || capable(CAP_SYS_ADMIN) || | ||
484 | drm_is_control_client(file_priv)) { | ||
485 | ret = fb->funcs->create_handle(fb, file_priv, | ||
486 | &r->handle); | ||
487 | } else { | ||
488 | /* GET_FB() is an unprivileged ioctl so we must not | ||
489 | * return a buffer-handle to non-master processes! For | ||
490 | * backwards-compatibility reasons, we cannot make | ||
491 | * GET_FB() privileged, so just return an invalid handle | ||
492 | * for non-masters. */ | ||
493 | r->handle = 0; | ||
494 | ret = 0; | ||
495 | } | ||
496 | } else { | ||
497 | ret = -ENODEV; | ||
498 | } | ||
499 | |||
500 | drm_framebuffer_unreference(fb); | ||
501 | |||
502 | return ret; | ||
503 | } | ||
504 | |||
505 | /** | ||
506 | * drm_mode_dirtyfb_ioctl - flush frontbuffer rendering on an FB | ||
507 | * @dev: drm device for the ioctl | ||
508 | * @data: data pointer for the ioctl | ||
509 | * @file_priv: drm file for the ioctl call | ||
510 | * | ||
511 | * Lookup the FB and flush out the damaged area supplied by userspace as a clip | ||
512 | * rectangle list. Generic userspace which does frontbuffer rendering must call | ||
513 | * this ioctl to flush out the changes on manual-update display outputs, e.g. | ||
514 | * usb display-link, mipi manual update panels or edp panel self refresh modes. | ||
515 | * | ||
516 | * Modesetting drivers which always update the frontbuffer do not need to | ||
517 | * implement the corresponding ->dirty framebuffer callback. | ||
518 | * | ||
519 | * Called by the user via ioctl. | ||
520 | * | ||
521 | * Returns: | ||
522 | * Zero on success, negative errno on failure. | ||
523 | */ | ||
524 | int drm_mode_dirtyfb_ioctl(struct drm_device *dev, | ||
525 | void *data, struct drm_file *file_priv) | ||
526 | { | ||
527 | struct drm_clip_rect __user *clips_ptr; | ||
528 | struct drm_clip_rect *clips = NULL; | ||
529 | struct drm_mode_fb_dirty_cmd *r = data; | ||
530 | struct drm_framebuffer *fb; | ||
531 | unsigned flags; | ||
532 | int num_clips; | ||
533 | int ret; | ||
534 | |||
535 | if (!drm_core_check_feature(dev, DRIVER_MODESET)) | ||
536 | return -EINVAL; | ||
537 | |||
538 | fb = drm_framebuffer_lookup(dev, r->fb_id); | ||
539 | if (!fb) | ||
540 | return -ENOENT; | ||
541 | |||
542 | num_clips = r->num_clips; | ||
543 | clips_ptr = (struct drm_clip_rect __user *)(unsigned long)r->clips_ptr; | ||
544 | |||
545 | if (!num_clips != !clips_ptr) { | ||
546 | ret = -EINVAL; | ||
547 | goto out_err1; | ||
548 | } | ||
549 | |||
550 | flags = DRM_MODE_FB_DIRTY_FLAGS & r->flags; | ||
551 | |||
552 | /* If userspace annotates copy, clips must come in pairs */ | ||
553 | if (flags & DRM_MODE_FB_DIRTY_ANNOTATE_COPY && (num_clips % 2)) { | ||
554 | ret = -EINVAL; | ||
555 | goto out_err1; | ||
556 | } | ||
557 | |||
558 | if (num_clips && clips_ptr) { | ||
559 | if (num_clips < 0 || num_clips > DRM_MODE_FB_DIRTY_MAX_CLIPS) { | ||
560 | ret = -EINVAL; | ||
561 | goto out_err1; | ||
562 | } | ||
563 | clips = kcalloc(num_clips, sizeof(*clips), GFP_KERNEL); | ||
564 | if (!clips) { | ||
565 | ret = -ENOMEM; | ||
566 | goto out_err1; | ||
567 | } | ||
568 | |||
569 | ret = copy_from_user(clips, clips_ptr, | ||
570 | num_clips * sizeof(*clips)); | ||
571 | if (ret) { | ||
572 | ret = -EFAULT; | ||
573 | goto out_err2; | ||
574 | } | ||
575 | } | ||
576 | |||
577 | if (fb->funcs->dirty) { | ||
578 | ret = fb->funcs->dirty(fb, file_priv, flags, r->color, | ||
579 | clips, num_clips); | ||
580 | } else { | ||
581 | ret = -ENOSYS; | ||
582 | } | ||
583 | |||
584 | out_err2: | ||
585 | kfree(clips); | ||
586 | out_err1: | ||
587 | drm_framebuffer_unreference(fb); | ||
588 | |||
589 | return ret; | ||
590 | } | ||
591 | |||
592 | /** | ||
593 | * drm_fb_release - remove and free the FBs on this file | ||
594 | * @priv: drm file for the ioctl | ||
595 | * | ||
596 | * Destroy all the FBs associated with @filp. | ||
597 | * | ||
598 | * Called by the user via ioctl. | ||
599 | * | ||
600 | * Returns: | ||
601 | * Zero on success, negative errno on failure. | ||
602 | */ | ||
603 | void drm_fb_release(struct drm_file *priv) | ||
604 | { | ||
605 | struct drm_framebuffer *fb, *tfb; | ||
606 | struct drm_mode_rmfb_work arg; | ||
607 | |||
608 | INIT_LIST_HEAD(&arg.fbs); | ||
609 | |||
610 | /* | ||
611 | * When the file gets released that means no one else can access the fb | ||
612 | * list any more, so no need to grab fpriv->fbs_lock. And we need to | ||
613 | * avoid upsetting lockdep since the universal cursor code adds a | ||
614 | * framebuffer while holding mutex locks. | ||
615 | * | ||
616 | * Note that a real deadlock between fpriv->fbs_lock and the modeset | ||
617 | * locks is impossible here since no one else but this function can get | ||
618 | * at it any more. | ||
619 | */ | ||
620 | list_for_each_entry_safe(fb, tfb, &priv->fbs, filp_head) { | ||
621 | if (drm_framebuffer_read_refcount(fb) > 1) { | ||
622 | list_move_tail(&fb->filp_head, &arg.fbs); | ||
623 | } else { | ||
624 | list_del_init(&fb->filp_head); | ||
625 | |||
626 | /* This drops the fpriv->fbs reference. */ | ||
627 | drm_framebuffer_unreference(fb); | ||
628 | } | ||
629 | } | ||
630 | |||
631 | if (!list_empty(&arg.fbs)) { | ||
632 | INIT_WORK_ONSTACK(&arg.work, drm_mode_rmfb_work_fn); | ||
633 | |||
634 | schedule_work(&arg.work); | ||
635 | flush_work(&arg.work); | ||
636 | destroy_work_on_stack(&arg.work); | ||
637 | } | ||
638 | } | ||
639 | |||
640 | void drm_framebuffer_free(struct kref *kref) | ||
641 | { | ||
642 | struct drm_framebuffer *fb = | ||
643 | container_of(kref, struct drm_framebuffer, base.refcount); | ||
644 | struct drm_device *dev = fb->dev; | ||
645 | |||
646 | /* | ||
647 | * The lookup idr holds a weak reference, which has not necessarily been | ||
648 | * removed at this point. Check for that. | ||
649 | */ | ||
650 | drm_mode_object_unregister(dev, &fb->base); | ||
651 | |||
652 | fb->funcs->destroy(fb); | ||
653 | } | ||
654 | |||
655 | /** | ||
656 | * drm_framebuffer_init - initialize a framebuffer | ||
657 | * @dev: DRM device | ||
658 | * @fb: framebuffer to be initialized | ||
659 | * @funcs: ... with these functions | ||
660 | * | ||
661 | * Allocates an ID for the framebuffer's parent mode object, sets its mode | ||
662 | * functions & device file and adds it to the master fd list. | ||
663 | * | ||
664 | * IMPORTANT: | ||
665 | * This functions publishes the fb and makes it available for concurrent access | ||
666 | * by other users. Which means by this point the fb _must_ be fully set up - | ||
667 | * since all the fb attributes are invariant over its lifetime, no further | ||
668 | * locking but only correct reference counting is required. | ||
669 | * | ||
670 | * Returns: | ||
671 | * Zero on success, error code on failure. | ||
672 | */ | ||
673 | int drm_framebuffer_init(struct drm_device *dev, struct drm_framebuffer *fb, | ||
674 | const struct drm_framebuffer_funcs *funcs) | ||
675 | { | ||
676 | int ret; | ||
677 | |||
678 | INIT_LIST_HEAD(&fb->filp_head); | ||
679 | fb->dev = dev; | ||
680 | fb->funcs = funcs; | ||
681 | |||
682 | ret = drm_mode_object_get_reg(dev, &fb->base, DRM_MODE_OBJECT_FB, | ||
683 | false, drm_framebuffer_free); | ||
684 | if (ret) | ||
685 | goto out; | ||
686 | |||
687 | mutex_lock(&dev->mode_config.fb_lock); | ||
688 | dev->mode_config.num_fb++; | ||
689 | list_add(&fb->head, &dev->mode_config.fb_list); | ||
690 | mutex_unlock(&dev->mode_config.fb_lock); | ||
691 | |||
692 | drm_mode_object_register(dev, &fb->base); | ||
693 | out: | ||
694 | return ret; | ||
695 | } | ||
696 | EXPORT_SYMBOL(drm_framebuffer_init); | ||
697 | |||
698 | /** | ||
699 | * drm_framebuffer_lookup - look up a drm framebuffer and grab a reference | ||
700 | * @dev: drm device | ||
701 | * @id: id of the fb object | ||
702 | * | ||
703 | * If successful, this grabs an additional reference to the framebuffer - | ||
704 | * callers need to make sure to eventually unreference the returned framebuffer | ||
705 | * again, using @drm_framebuffer_unreference. | ||
706 | */ | ||
707 | struct drm_framebuffer *drm_framebuffer_lookup(struct drm_device *dev, | ||
708 | uint32_t id) | ||
709 | { | ||
710 | struct drm_mode_object *obj; | ||
711 | struct drm_framebuffer *fb = NULL; | ||
712 | |||
713 | obj = __drm_mode_object_find(dev, id, DRM_MODE_OBJECT_FB); | ||
714 | if (obj) | ||
715 | fb = obj_to_fb(obj); | ||
716 | return fb; | ||
717 | } | ||
718 | EXPORT_SYMBOL(drm_framebuffer_lookup); | ||
719 | |||
720 | /** | ||
721 | * drm_framebuffer_unregister_private - unregister a private fb from the lookup idr | ||
722 | * @fb: fb to unregister | ||
723 | * | ||
724 | * Drivers need to call this when cleaning up driver-private framebuffers, e.g. | ||
725 | * those used for fbdev. Note that the caller must hold a reference of it's own, | ||
726 | * i.e. the object may not be destroyed through this call (since it'll lead to a | ||
727 | * locking inversion). | ||
728 | */ | ||
729 | void drm_framebuffer_unregister_private(struct drm_framebuffer *fb) | ||
730 | { | ||
731 | struct drm_device *dev; | ||
732 | |||
733 | if (!fb) | ||
734 | return; | ||
735 | |||
736 | dev = fb->dev; | ||
737 | |||
738 | /* Mark fb as reaped and drop idr ref. */ | ||
739 | drm_mode_object_unregister(dev, &fb->base); | ||
740 | } | ||
741 | EXPORT_SYMBOL(drm_framebuffer_unregister_private); | ||
742 | |||
743 | /** | ||
744 | * drm_framebuffer_cleanup - remove a framebuffer object | ||
745 | * @fb: framebuffer to remove | ||
746 | * | ||
747 | * Cleanup framebuffer. This function is intended to be used from the drivers | ||
748 | * ->destroy callback. It can also be used to clean up driver private | ||
749 | * framebuffers embedded into a larger structure. | ||
750 | * | ||
751 | * Note that this function does not remove the fb from active usuage - if it is | ||
752 | * still used anywhere, hilarity can ensue since userspace could call getfb on | ||
753 | * the id and get back -EINVAL. Obviously no concern at driver unload time. | ||
754 | * | ||
755 | * Also, the framebuffer will not be removed from the lookup idr - for | ||
756 | * user-created framebuffers this will happen in in the rmfb ioctl. For | ||
757 | * driver-private objects (e.g. for fbdev) drivers need to explicitly call | ||
758 | * drm_framebuffer_unregister_private. | ||
759 | */ | ||
760 | void drm_framebuffer_cleanup(struct drm_framebuffer *fb) | ||
761 | { | ||
762 | struct drm_device *dev = fb->dev; | ||
763 | |||
764 | mutex_lock(&dev->mode_config.fb_lock); | ||
765 | list_del(&fb->head); | ||
766 | dev->mode_config.num_fb--; | ||
767 | mutex_unlock(&dev->mode_config.fb_lock); | ||
768 | } | ||
769 | EXPORT_SYMBOL(drm_framebuffer_cleanup); | ||
770 | |||
771 | /** | ||
772 | * drm_framebuffer_remove - remove and unreference a framebuffer object | ||
773 | * @fb: framebuffer to remove | ||
774 | * | ||
775 | * Scans all the CRTCs and planes in @dev's mode_config. If they're | ||
776 | * using @fb, removes it, setting it to NULL. Then drops the reference to the | ||
777 | * passed-in framebuffer. Might take the modeset locks. | ||
778 | * | ||
779 | * Note that this function optimizes the cleanup away if the caller holds the | ||
780 | * last reference to the framebuffer. It is also guaranteed to not take the | ||
781 | * modeset locks in this case. | ||
782 | */ | ||
783 | void drm_framebuffer_remove(struct drm_framebuffer *fb) | ||
784 | { | ||
785 | struct drm_device *dev; | ||
786 | struct drm_crtc *crtc; | ||
787 | struct drm_plane *plane; | ||
788 | |||
789 | if (!fb) | ||
790 | return; | ||
791 | |||
792 | dev = fb->dev; | ||
793 | |||
794 | WARN_ON(!list_empty(&fb->filp_head)); | ||
795 | |||
796 | /* | ||
797 | * drm ABI mandates that we remove any deleted framebuffers from active | ||
798 | * useage. But since most sane clients only remove framebuffers they no | ||
799 | * longer need, try to optimize this away. | ||
800 | * | ||
801 | * Since we're holding a reference ourselves, observing a refcount of 1 | ||
802 | * means that we're the last holder and can skip it. Also, the refcount | ||
803 | * can never increase from 1 again, so we don't need any barriers or | ||
804 | * locks. | ||
805 | * | ||
806 | * Note that userspace could try to race with use and instate a new | ||
807 | * usage _after_ we've cleared all current ones. End result will be an | ||
808 | * in-use fb with fb-id == 0. Userspace is allowed to shoot its own foot | ||
809 | * in this manner. | ||
810 | */ | ||
811 | if (drm_framebuffer_read_refcount(fb) > 1) { | ||
812 | drm_modeset_lock_all(dev); | ||
813 | /* remove from any CRTC */ | ||
814 | drm_for_each_crtc(crtc, dev) { | ||
815 | if (crtc->primary->fb == fb) { | ||
816 | /* should turn off the crtc */ | ||
817 | if (drm_crtc_force_disable(crtc)) | ||
818 | DRM_ERROR("failed to reset crtc %p when fb was deleted\n", crtc); | ||
819 | } | ||
820 | } | ||
821 | |||
822 | drm_for_each_plane(plane, dev) { | ||
823 | if (plane->fb == fb) | ||
824 | drm_plane_force_disable(plane); | ||
825 | } | ||
826 | drm_modeset_unlock_all(dev); | ||
827 | } | ||
828 | |||
829 | drm_framebuffer_unreference(fb); | ||
830 | } | ||
831 | EXPORT_SYMBOL(drm_framebuffer_remove); | ||
diff --git a/drivers/gpu/drm/drm_ioc32.c b/drivers/gpu/drm/drm_ioc32.c index 57676f8d7ecf..32a489b0faff 100644 --- a/drivers/gpu/drm/drm_ioc32.c +++ b/drivers/gpu/drm/drm_ioc32.c | |||
@@ -346,6 +346,7 @@ static int compat_drm_getstats(struct file *file, unsigned int cmd, | |||
346 | struct drm_stats __user *stats; | 346 | struct drm_stats __user *stats; |
347 | int i, err; | 347 | int i, err; |
348 | 348 | ||
349 | memset(&s32, 0, sizeof(drm_stats32_t)); | ||
349 | stats = compat_alloc_user_space(sizeof(*stats)); | 350 | stats = compat_alloc_user_space(sizeof(*stats)); |
350 | if (!stats) | 351 | if (!stats) |
351 | return -EFAULT; | 352 | return -EFAULT; |
diff --git a/drivers/gpu/drm/drm_irq.c b/drivers/gpu/drm/drm_irq.c index c0c3f2006203..404a1ce7730c 100644 --- a/drivers/gpu/drm/drm_irq.c +++ b/drivers/gpu/drm/drm_irq.c | |||
@@ -713,10 +713,10 @@ EXPORT_SYMBOL(drm_calc_timestamping_constants); | |||
713 | * Negative value on error, failure or if not supported in current | 713 | * Negative value on error, failure or if not supported in current |
714 | * video mode: | 714 | * video mode: |
715 | * | 715 | * |
716 | * -EINVAL - Invalid CRTC. | 716 | * -EINVAL Invalid CRTC. |
717 | * -EAGAIN - Temporary unavailable, e.g., called before initial modeset. | 717 | * -EAGAIN Temporary unavailable, e.g., called before initial modeset. |
718 | * -ENOTSUPP - Function not supported in current display mode. | 718 | * -ENOTSUPP Function not supported in current display mode. |
719 | * -EIO - Failed, e.g., due to failed scanout position query. | 719 | * -EIO Failed, e.g., due to failed scanout position query. |
720 | * | 720 | * |
721 | * Returns or'ed positive status flags on success: | 721 | * Returns or'ed positive status flags on success: |
722 | * | 722 | * |
diff --git a/drivers/gpu/drm/drm_kms_helper_common.c b/drivers/gpu/drm/drm_kms_helper_common.c index 3187c4bb01cb..45db36cd3d20 100644 --- a/drivers/gpu/drm/drm_kms_helper_common.c +++ b/drivers/gpu/drm/drm_kms_helper_common.c | |||
@@ -27,7 +27,8 @@ | |||
27 | 27 | ||
28 | #include <drm/drmP.h> | 28 | #include <drm/drmP.h> |
29 | #include <drm/drm_fb_helper.h> | 29 | #include <drm/drm_fb_helper.h> |
30 | #include <drm/drm_dp_aux_dev.h> | 30 | |
31 | #include "drm_crtc_helper_internal.h" | ||
31 | 32 | ||
32 | MODULE_AUTHOR("David Airlie, Jesse Barnes"); | 33 | MODULE_AUTHOR("David Airlie, Jesse Barnes"); |
33 | MODULE_DESCRIPTION("DRM KMS helper"); | 34 | MODULE_DESCRIPTION("DRM KMS helper"); |
diff --git a/drivers/gpu/drm/drm_modes.c b/drivers/gpu/drm/drm_modes.c index 15704873fd61..53f07ac7c174 100644 --- a/drivers/gpu/drm/drm_modes.c +++ b/drivers/gpu/drm/drm_modes.c | |||
@@ -657,6 +657,15 @@ void drm_display_mode_to_videomode(const struct drm_display_mode *dmode, | |||
657 | } | 657 | } |
658 | EXPORT_SYMBOL_GPL(drm_display_mode_to_videomode); | 658 | EXPORT_SYMBOL_GPL(drm_display_mode_to_videomode); |
659 | 659 | ||
660 | /** | ||
661 | * drm_bus_flags_from_videomode - extract information about pixelclk and | ||
662 | * DE polarity from videomode and store it in a separate variable | ||
663 | * @vm: videomode structure to use | ||
664 | * @bus_flags: information about pixelclk and DE polarity will be stored here | ||
665 | * | ||
666 | * Sets DRM_BUS_FLAG_DE_(LOW|HIGH) and DRM_BUS_FLAG_PIXDATA_(POS|NEG)EDGE | ||
667 | * in @bus_flags according to DISPLAY_FLAGS found in @vm | ||
668 | */ | ||
660 | void drm_bus_flags_from_videomode(const struct videomode *vm, u32 *bus_flags) | 669 | void drm_bus_flags_from_videomode(const struct videomode *vm, u32 *bus_flags) |
661 | { | 670 | { |
662 | *bus_flags = 0; | 671 | *bus_flags = 0; |
@@ -677,6 +686,7 @@ EXPORT_SYMBOL_GPL(drm_bus_flags_from_videomode); | |||
677 | * of_get_drm_display_mode - get a drm_display_mode from devicetree | 686 | * of_get_drm_display_mode - get a drm_display_mode from devicetree |
678 | * @np: device_node with the timing specification | 687 | * @np: device_node with the timing specification |
679 | * @dmode: will be set to the return value | 688 | * @dmode: will be set to the return value |
689 | * @bus_flags: information about pixelclk and DE polarity | ||
680 | * @index: index into the list of display timings in devicetree | 690 | * @index: index into the list of display timings in devicetree |
681 | * | 691 | * |
682 | * This function is expensive and should only be used, if only one mode is to be | 692 | * This function is expensive and should only be used, if only one mode is to be |
diff --git a/drivers/gpu/drm/drm_modeset_helper.c b/drivers/gpu/drm/drm_modeset_helper.c new file mode 100644 index 000000000000..1d45738f8f98 --- /dev/null +++ b/drivers/gpu/drm/drm_modeset_helper.c | |||
@@ -0,0 +1,153 @@ | |||
1 | /* | ||
2 | * Copyright (c) 2016 Intel Corporation | ||
3 | * | ||
4 | * Permission to use, copy, modify, distribute, and sell this software and its | ||
5 | * documentation for any purpose is hereby granted without fee, provided that | ||
6 | * the above copyright notice appear in all copies and that both that copyright | ||
7 | * notice and this permission notice appear in supporting documentation, and | ||
8 | * that the name of the copyright holders not be used in advertising or | ||
9 | * publicity pertaining to distribution of the software without specific, | ||
10 | * written prior permission. The copyright holders make no representations | ||
11 | * about the suitability of this software for any purpose. It is provided "as | ||
12 | * is" without express or implied warranty. | ||
13 | * | ||
14 | * THE COPYRIGHT HOLDERS DISCLAIM ALL WARRANTIES WITH REGARD TO THIS SOFTWARE, | ||
15 | * INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS, IN NO | ||
16 | * EVENT SHALL THE COPYRIGHT HOLDERS BE LIABLE FOR ANY SPECIAL, INDIRECT OR | ||
17 | * CONSEQUENTIAL DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM LOSS OF USE, | ||
18 | * DATA OR PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER | ||
19 | * TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR PERFORMANCE | ||
20 | * OF THIS SOFTWARE. | ||
21 | */ | ||
22 | |||
23 | #include <drm/drm_modeset_helper.h> | ||
24 | #include <drm/drm_plane_helper.h> | ||
25 | |||
26 | /** | ||
27 | * DOC: aux kms helpers | ||
28 | * | ||
29 | * This helper library contains various one-off functions which don't really fit | ||
30 | * anywhere else in the DRM modeset helper library. | ||
31 | */ | ||
32 | |||
33 | /** | ||
34 | * drm_helper_move_panel_connectors_to_head() - move panels to the front in the | ||
35 | * connector list | ||
36 | * @dev: drm device to operate on | ||
37 | * | ||
38 | * Some userspace presumes that the first connected connector is the main | ||
39 | * display, where it's supposed to display e.g. the login screen. For | ||
40 | * laptops, this should be the main panel. Use this function to sort all | ||
41 | * (eDP/LVDS) panels to the front of the connector list, instead of | ||
42 | * painstakingly trying to initialize them in the right order. | ||
43 | */ | ||
44 | void drm_helper_move_panel_connectors_to_head(struct drm_device *dev) | ||
45 | { | ||
46 | struct drm_connector *connector, *tmp; | ||
47 | struct list_head panel_list; | ||
48 | |||
49 | INIT_LIST_HEAD(&panel_list); | ||
50 | |||
51 | list_for_each_entry_safe(connector, tmp, | ||
52 | &dev->mode_config.connector_list, head) { | ||
53 | if (connector->connector_type == DRM_MODE_CONNECTOR_LVDS || | ||
54 | connector->connector_type == DRM_MODE_CONNECTOR_eDP) | ||
55 | list_move_tail(&connector->head, &panel_list); | ||
56 | } | ||
57 | |||
58 | list_splice(&panel_list, &dev->mode_config.connector_list); | ||
59 | } | ||
60 | EXPORT_SYMBOL(drm_helper_move_panel_connectors_to_head); | ||
61 | |||
62 | /** | ||
63 | * drm_helper_mode_fill_fb_struct - fill out framebuffer metadata | ||
64 | * @fb: drm_framebuffer object to fill out | ||
65 | * @mode_cmd: metadata from the userspace fb creation request | ||
66 | * | ||
67 | * This helper can be used in a drivers fb_create callback to pre-fill the fb's | ||
68 | * metadata fields. | ||
69 | */ | ||
70 | void drm_helper_mode_fill_fb_struct(struct drm_framebuffer *fb, | ||
71 | const struct drm_mode_fb_cmd2 *mode_cmd) | ||
72 | { | ||
73 | int i; | ||
74 | |||
75 | fb->width = mode_cmd->width; | ||
76 | fb->height = mode_cmd->height; | ||
77 | for (i = 0; i < 4; i++) { | ||
78 | fb->pitches[i] = mode_cmd->pitches[i]; | ||
79 | fb->offsets[i] = mode_cmd->offsets[i]; | ||
80 | fb->modifier[i] = mode_cmd->modifier[i]; | ||
81 | } | ||
82 | drm_fb_get_bpp_depth(mode_cmd->pixel_format, &fb->depth, | ||
83 | &fb->bits_per_pixel); | ||
84 | fb->pixel_format = mode_cmd->pixel_format; | ||
85 | fb->flags = mode_cmd->flags; | ||
86 | } | ||
87 | EXPORT_SYMBOL(drm_helper_mode_fill_fb_struct); | ||
88 | |||
89 | /* | ||
90 | * This is the minimal list of formats that seem to be safe for modeset use | ||
91 | * with all current DRM drivers. Most hardware can actually support more | ||
92 | * formats than this and drivers may specify a more accurate list when | ||
93 | * creating the primary plane. However drivers that still call | ||
94 | * drm_plane_init() will use this minimal format list as the default. | ||
95 | */ | ||
96 | static const uint32_t safe_modeset_formats[] = { | ||
97 | DRM_FORMAT_XRGB8888, | ||
98 | DRM_FORMAT_ARGB8888, | ||
99 | }; | ||
100 | |||
101 | static struct drm_plane *create_primary_plane(struct drm_device *dev) | ||
102 | { | ||
103 | struct drm_plane *primary; | ||
104 | int ret; | ||
105 | |||
106 | primary = kzalloc(sizeof(*primary), GFP_KERNEL); | ||
107 | if (primary == NULL) { | ||
108 | DRM_DEBUG_KMS("Failed to allocate primary plane\n"); | ||
109 | return NULL; | ||
110 | } | ||
111 | |||
112 | /* | ||
113 | * Remove the format_default field from drm_plane when dropping | ||
114 | * this helper. | ||
115 | */ | ||
116 | primary->format_default = true; | ||
117 | |||
118 | /* possible_crtc's will be filled in later by crtc_init */ | ||
119 | ret = drm_universal_plane_init(dev, primary, 0, | ||
120 | &drm_primary_helper_funcs, | ||
121 | safe_modeset_formats, | ||
122 | ARRAY_SIZE(safe_modeset_formats), | ||
123 | DRM_PLANE_TYPE_PRIMARY, NULL); | ||
124 | if (ret) { | ||
125 | kfree(primary); | ||
126 | primary = NULL; | ||
127 | } | ||
128 | |||
129 | return primary; | ||
130 | } | ||
131 | |||
132 | /** | ||
133 | * drm_crtc_init - Legacy CRTC initialization function | ||
134 | * @dev: DRM device | ||
135 | * @crtc: CRTC object to init | ||
136 | * @funcs: callbacks for the new CRTC | ||
137 | * | ||
138 | * Initialize a CRTC object with a default helper-provided primary plane and no | ||
139 | * cursor plane. | ||
140 | * | ||
141 | * Returns: | ||
142 | * Zero on success, error code on failure. | ||
143 | */ | ||
144 | int drm_crtc_init(struct drm_device *dev, struct drm_crtc *crtc, | ||
145 | const struct drm_crtc_funcs *funcs) | ||
146 | { | ||
147 | struct drm_plane *primary; | ||
148 | |||
149 | primary = create_primary_plane(dev); | ||
150 | return drm_crtc_init_with_planes(dev, crtc, primary, NULL, funcs, | ||
151 | NULL); | ||
152 | } | ||
153 | EXPORT_SYMBOL(drm_crtc_init); | ||
diff --git a/drivers/gpu/drm/drm_plane_helper.c b/drivers/gpu/drm/drm_plane_helper.c index b522aabd1ab0..7899fc1dcdb0 100644 --- a/drivers/gpu/drm/drm_plane_helper.c +++ b/drivers/gpu/drm/drm_plane_helper.c | |||
@@ -64,18 +64,6 @@ | |||
64 | */ | 64 | */ |
65 | 65 | ||
66 | /* | 66 | /* |
67 | * This is the minimal list of formats that seem to be safe for modeset use | ||
68 | * with all current DRM drivers. Most hardware can actually support more | ||
69 | * formats than this and drivers may specify a more accurate list when | ||
70 | * creating the primary plane. However drivers that still call | ||
71 | * drm_plane_init() will use this minimal format list as the default. | ||
72 | */ | ||
73 | static const uint32_t safe_modeset_formats[] = { | ||
74 | DRM_FORMAT_XRGB8888, | ||
75 | DRM_FORMAT_ARGB8888, | ||
76 | }; | ||
77 | |||
78 | /* | ||
79 | * Returns the connectors currently associated with a CRTC. This function | 67 | * Returns the connectors currently associated with a CRTC. This function |
80 | * should be called twice: once with a NULL connector list to retrieve | 68 | * should be called twice: once with a NULL connector list to retrieve |
81 | * the list size, and once with the properly allocated list to be filled in. | 69 | * the list size, and once with the properly allocated list to be filled in. |
@@ -211,7 +199,7 @@ EXPORT_SYMBOL(drm_plane_helper_check_state); | |||
211 | * @crtc: owning CRTC of owning plane | 199 | * @crtc: owning CRTC of owning plane |
212 | * @fb: framebuffer to flip onto plane | 200 | * @fb: framebuffer to flip onto plane |
213 | * @src: source coordinates in 16.16 fixed point | 201 | * @src: source coordinates in 16.16 fixed point |
214 | * @dest: integer destination coordinates | 202 | * @dst: integer destination coordinates |
215 | * @clip: integer clipping coordinates | 203 | * @clip: integer clipping coordinates |
216 | * @rotation: plane rotation | 204 | * @rotation: plane rotation |
217 | * @min_scale: minimum @src:@dest scaling factor in 16.16 fixed point | 205 | * @min_scale: minimum @src:@dest scaling factor in 16.16 fixed point |
@@ -438,60 +426,6 @@ const struct drm_plane_funcs drm_primary_helper_funcs = { | |||
438 | }; | 426 | }; |
439 | EXPORT_SYMBOL(drm_primary_helper_funcs); | 427 | EXPORT_SYMBOL(drm_primary_helper_funcs); |
440 | 428 | ||
441 | static struct drm_plane *create_primary_plane(struct drm_device *dev) | ||
442 | { | ||
443 | struct drm_plane *primary; | ||
444 | int ret; | ||
445 | |||
446 | primary = kzalloc(sizeof(*primary), GFP_KERNEL); | ||
447 | if (primary == NULL) { | ||
448 | DRM_DEBUG_KMS("Failed to allocate primary plane\n"); | ||
449 | return NULL; | ||
450 | } | ||
451 | |||
452 | /* | ||
453 | * Remove the format_default field from drm_plane when dropping | ||
454 | * this helper. | ||
455 | */ | ||
456 | primary->format_default = true; | ||
457 | |||
458 | /* possible_crtc's will be filled in later by crtc_init */ | ||
459 | ret = drm_universal_plane_init(dev, primary, 0, | ||
460 | &drm_primary_helper_funcs, | ||
461 | safe_modeset_formats, | ||
462 | ARRAY_SIZE(safe_modeset_formats), | ||
463 | DRM_PLANE_TYPE_PRIMARY, NULL); | ||
464 | if (ret) { | ||
465 | kfree(primary); | ||
466 | primary = NULL; | ||
467 | } | ||
468 | |||
469 | return primary; | ||
470 | } | ||
471 | |||
472 | /** | ||
473 | * drm_crtc_init - Legacy CRTC initialization function | ||
474 | * @dev: DRM device | ||
475 | * @crtc: CRTC object to init | ||
476 | * @funcs: callbacks for the new CRTC | ||
477 | * | ||
478 | * Initialize a CRTC object with a default helper-provided primary plane and no | ||
479 | * cursor plane. | ||
480 | * | ||
481 | * Returns: | ||
482 | * Zero on success, error code on failure. | ||
483 | */ | ||
484 | int drm_crtc_init(struct drm_device *dev, struct drm_crtc *crtc, | ||
485 | const struct drm_crtc_funcs *funcs) | ||
486 | { | ||
487 | struct drm_plane *primary; | ||
488 | |||
489 | primary = create_primary_plane(dev); | ||
490 | return drm_crtc_init_with_planes(dev, crtc, primary, NULL, funcs, | ||
491 | NULL); | ||
492 | } | ||
493 | EXPORT_SYMBOL(drm_crtc_init); | ||
494 | |||
495 | int drm_plane_helper_commit(struct drm_plane *plane, | 429 | int drm_plane_helper_commit(struct drm_plane *plane, |
496 | struct drm_plane_state *plane_state, | 430 | struct drm_plane_state *plane_state, |
497 | struct drm_framebuffer *old_fb) | 431 | struct drm_framebuffer *old_fb) |
diff --git a/drivers/gpu/drm/drm_simple_kms_helper.c b/drivers/gpu/drm/drm_simple_kms_helper.c index 0a02efe978ee..bada17166512 100644 --- a/drivers/gpu/drm/drm_simple_kms_helper.c +++ b/drivers/gpu/drm/drm_simple_kms_helper.c | |||
@@ -137,7 +137,7 @@ static const struct drm_plane_funcs drm_simple_kms_plane_funcs = { | |||
137 | * @dev: DRM device | 137 | * @dev: DRM device |
138 | * @pipe: simple display pipe object to initialize | 138 | * @pipe: simple display pipe object to initialize |
139 | * @funcs: callbacks for the display pipe (optional) | 139 | * @funcs: callbacks for the display pipe (optional) |
140 | * @formats: array of supported formats (%DRM_FORMAT_*) | 140 | * @formats: array of supported formats (DRM_FORMAT\_\*) |
141 | * @format_count: number of elements in @formats | 141 | * @format_count: number of elements in @formats |
142 | * @connector: connector to attach and register | 142 | * @connector: connector to attach and register |
143 | * | 143 | * |
diff --git a/drivers/gpu/drm/etnaviv/etnaviv_drv.c b/drivers/gpu/drm/etnaviv/etnaviv_drv.c index ffd1b32caa8d..e3164d90399d 100644 --- a/drivers/gpu/drm/etnaviv/etnaviv_drv.c +++ b/drivers/gpu/drm/etnaviv/etnaviv_drv.c | |||
@@ -488,8 +488,7 @@ static const struct file_operations fops = { | |||
488 | }; | 488 | }; |
489 | 489 | ||
490 | static struct drm_driver etnaviv_drm_driver = { | 490 | static struct drm_driver etnaviv_drm_driver = { |
491 | .driver_features = DRIVER_HAVE_IRQ | | 491 | .driver_features = DRIVER_GEM | |
492 | DRIVER_GEM | | ||
493 | DRIVER_PRIME | | 492 | DRIVER_PRIME | |
494 | DRIVER_RENDER, | 493 | DRIVER_RENDER, |
495 | .open = etnaviv_open, | 494 | .open = etnaviv_open, |
@@ -533,8 +532,6 @@ static int etnaviv_bind(struct device *dev) | |||
533 | if (!drm) | 532 | if (!drm) |
534 | return -ENOMEM; | 533 | return -ENOMEM; |
535 | 534 | ||
536 | drm->platformdev = to_platform_device(dev); | ||
537 | |||
538 | priv = kzalloc(sizeof(*priv), GFP_KERNEL); | 535 | priv = kzalloc(sizeof(*priv), GFP_KERNEL); |
539 | if (!priv) { | 536 | if (!priv) { |
540 | dev_err(dev, "failed to allocate private data\n"); | 537 | dev_err(dev, "failed to allocate private data\n"); |
diff --git a/drivers/gpu/drm/fsl-dcu/fsl_dcu_drm_plane.c b/drivers/gpu/drm/fsl-dcu/fsl_dcu_drm_plane.c index e50467a0deb0..a7e5486bd1e9 100644 --- a/drivers/gpu/drm/fsl-dcu/fsl_dcu_drm_plane.c +++ b/drivers/gpu/drm/fsl-dcu/fsl_dcu_drm_plane.c | |||
@@ -169,25 +169,10 @@ static void fsl_dcu_drm_plane_atomic_update(struct drm_plane *plane, | |||
169 | return; | 169 | return; |
170 | } | 170 | } |
171 | 171 | ||
172 | static void | ||
173 | fsl_dcu_drm_plane_cleanup_fb(struct drm_plane *plane, | ||
174 | const struct drm_plane_state *new_state) | ||
175 | { | ||
176 | } | ||
177 | |||
178 | static int | ||
179 | fsl_dcu_drm_plane_prepare_fb(struct drm_plane *plane, | ||
180 | const struct drm_plane_state *new_state) | ||
181 | { | ||
182 | return 0; | ||
183 | } | ||
184 | |||
185 | static const struct drm_plane_helper_funcs fsl_dcu_drm_plane_helper_funcs = { | 172 | static const struct drm_plane_helper_funcs fsl_dcu_drm_plane_helper_funcs = { |
186 | .atomic_check = fsl_dcu_drm_plane_atomic_check, | 173 | .atomic_check = fsl_dcu_drm_plane_atomic_check, |
187 | .atomic_disable = fsl_dcu_drm_plane_atomic_disable, | 174 | .atomic_disable = fsl_dcu_drm_plane_atomic_disable, |
188 | .atomic_update = fsl_dcu_drm_plane_atomic_update, | 175 | .atomic_update = fsl_dcu_drm_plane_atomic_update, |
189 | .cleanup_fb = fsl_dcu_drm_plane_cleanup_fb, | ||
190 | .prepare_fb = fsl_dcu_drm_plane_prepare_fb, | ||
191 | }; | 176 | }; |
192 | 177 | ||
193 | static void fsl_dcu_drm_plane_destroy(struct drm_plane *plane) | 178 | static void fsl_dcu_drm_plane_destroy(struct drm_plane *plane) |
diff --git a/drivers/gpu/drm/gma500/cdv_intel_lvds.c b/drivers/gpu/drm/gma500/cdv_intel_lvds.c index 38dc89083148..ea733ab5b1e0 100644 --- a/drivers/gpu/drm/gma500/cdv_intel_lvds.c +++ b/drivers/gpu/drm/gma500/cdv_intel_lvds.c | |||
@@ -415,14 +415,6 @@ static int cdv_intel_lvds_get_modes(struct drm_connector *connector) | |||
415 | if (ret) | 415 | if (ret) |
416 | return ret; | 416 | return ret; |
417 | 417 | ||
418 | /* Didn't get an EDID, so | ||
419 | * Set wide sync ranges so we get all modes | ||
420 | * handed to valid_mode for checking | ||
421 | */ | ||
422 | connector->display_info.min_vfreq = 0; | ||
423 | connector->display_info.max_vfreq = 200; | ||
424 | connector->display_info.min_hfreq = 0; | ||
425 | connector->display_info.max_hfreq = 200; | ||
426 | if (mode_dev->panel_fixed_mode != NULL) { | 418 | if (mode_dev->panel_fixed_mode != NULL) { |
427 | struct drm_display_mode *mode = | 419 | struct drm_display_mode *mode = |
428 | drm_mode_duplicate(dev, mode_dev->panel_fixed_mode); | 420 | drm_mode_duplicate(dev, mode_dev->panel_fixed_mode); |
diff --git a/drivers/gpu/drm/gma500/mdfld_dsi_output.c b/drivers/gpu/drm/gma500/mdfld_dsi_output.c index 907cb51795c3..acb3848ef1c9 100644 --- a/drivers/gpu/drm/gma500/mdfld_dsi_output.c +++ b/drivers/gpu/drm/gma500/mdfld_dsi_output.c | |||
@@ -335,11 +335,6 @@ static int mdfld_dsi_connector_get_modes(struct drm_connector *connector) | |||
335 | struct drm_display_mode *dup_mode = NULL; | 335 | struct drm_display_mode *dup_mode = NULL; |
336 | struct drm_device *dev = connector->dev; | 336 | struct drm_device *dev = connector->dev; |
337 | 337 | ||
338 | connector->display_info.min_vfreq = 0; | ||
339 | connector->display_info.max_vfreq = 200; | ||
340 | connector->display_info.min_hfreq = 0; | ||
341 | connector->display_info.max_hfreq = 200; | ||
342 | |||
343 | if (fixed_mode) { | 338 | if (fixed_mode) { |
344 | dev_dbg(dev->dev, "fixed_mode %dx%d\n", | 339 | dev_dbg(dev->dev, "fixed_mode %dx%d\n", |
345 | fixed_mode->hdisplay, fixed_mode->vdisplay); | 340 | fixed_mode->hdisplay, fixed_mode->vdisplay); |
diff --git a/drivers/gpu/drm/gma500/psb_intel_lvds.c b/drivers/gpu/drm/gma500/psb_intel_lvds.c index e55733ca46d2..fd7c91254841 100644 --- a/drivers/gpu/drm/gma500/psb_intel_lvds.c +++ b/drivers/gpu/drm/gma500/psb_intel_lvds.c | |||
@@ -530,15 +530,6 @@ static int psb_intel_lvds_get_modes(struct drm_connector *connector) | |||
530 | if (ret) | 530 | if (ret) |
531 | return ret; | 531 | return ret; |
532 | 532 | ||
533 | /* Didn't get an EDID, so | ||
534 | * Set wide sync ranges so we get all modes | ||
535 | * handed to valid_mode for checking | ||
536 | */ | ||
537 | connector->display_info.min_vfreq = 0; | ||
538 | connector->display_info.max_vfreq = 200; | ||
539 | connector->display_info.min_hfreq = 0; | ||
540 | connector->display_info.max_hfreq = 200; | ||
541 | |||
542 | if (mode_dev->panel_fixed_mode != NULL) { | 533 | if (mode_dev->panel_fixed_mode != NULL) { |
543 | struct drm_display_mode *mode = | 534 | struct drm_display_mode *mode = |
544 | drm_mode_duplicate(dev, mode_dev->panel_fixed_mode); | 535 | drm_mode_duplicate(dev, mode_dev->panel_fixed_mode); |
diff --git a/drivers/gpu/drm/hisilicon/kirin/kirin_drm_ade.c b/drivers/gpu/drm/hisilicon/kirin/kirin_drm_ade.c index c3707d47cd89..7e7a4d43d6b6 100644 --- a/drivers/gpu/drm/hisilicon/kirin/kirin_drm_ade.c +++ b/drivers/gpu/drm/hisilicon/kirin/kirin_drm_ade.c | |||
@@ -608,15 +608,17 @@ static void ade_rdma_set(void __iomem *base, struct drm_framebuffer *fb, | |||
608 | u32 ch, u32 y, u32 in_h, u32 fmt) | 608 | u32 ch, u32 y, u32 in_h, u32 fmt) |
609 | { | 609 | { |
610 | struct drm_gem_cma_object *obj = drm_fb_cma_get_gem_obj(fb, 0); | 610 | struct drm_gem_cma_object *obj = drm_fb_cma_get_gem_obj(fb, 0); |
611 | char *format_name; | ||
611 | u32 reg_ctrl, reg_addr, reg_size, reg_stride, reg_space, reg_en; | 612 | u32 reg_ctrl, reg_addr, reg_size, reg_stride, reg_space, reg_en; |
612 | u32 stride = fb->pitches[0]; | 613 | u32 stride = fb->pitches[0]; |
613 | u32 addr = (u32)obj->paddr + y * stride; | 614 | u32 addr = (u32)obj->paddr + y * stride; |
614 | 615 | ||
615 | DRM_DEBUG_DRIVER("rdma%d: (y=%d, height=%d), stride=%d, paddr=0x%x\n", | 616 | DRM_DEBUG_DRIVER("rdma%d: (y=%d, height=%d), stride=%d, paddr=0x%x\n", |
616 | ch + 1, y, in_h, stride, (u32)obj->paddr); | 617 | ch + 1, y, in_h, stride, (u32)obj->paddr); |
618 | format_name = drm_get_format_name(fb->pixel_format); | ||
617 | DRM_DEBUG_DRIVER("addr=0x%x, fb:%dx%d, pixel_format=%d(%s)\n", | 619 | DRM_DEBUG_DRIVER("addr=0x%x, fb:%dx%d, pixel_format=%d(%s)\n", |
618 | addr, fb->width, fb->height, fmt, | 620 | addr, fb->width, fb->height, fmt, format_name); |
619 | drm_get_format_name(fb->pixel_format)); | 621 | kfree(format_name); |
620 | 622 | ||
621 | /* get reg offset */ | 623 | /* get reg offset */ |
622 | reg_ctrl = RD_CH_CTRL(ch); | 624 | reg_ctrl = RD_CH_CTRL(ch); |
@@ -815,19 +817,6 @@ static void ade_disable_channel(struct ade_plane *aplane) | |||
815 | ade_compositor_routing_disable(base, ch); | 817 | ade_compositor_routing_disable(base, ch); |
816 | } | 818 | } |
817 | 819 | ||
818 | static int ade_plane_prepare_fb(struct drm_plane *plane, | ||
819 | const struct drm_plane_state *new_state) | ||
820 | { | ||
821 | /* do nothing */ | ||
822 | return 0; | ||
823 | } | ||
824 | |||
825 | static void ade_plane_cleanup_fb(struct drm_plane *plane, | ||
826 | const struct drm_plane_state *old_state) | ||
827 | { | ||
828 | /* do nothing */ | ||
829 | } | ||
830 | |||
831 | static int ade_plane_atomic_check(struct drm_plane *plane, | 820 | static int ade_plane_atomic_check(struct drm_plane *plane, |
832 | struct drm_plane_state *state) | 821 | struct drm_plane_state *state) |
833 | { | 822 | { |
@@ -895,8 +884,6 @@ static void ade_plane_atomic_disable(struct drm_plane *plane, | |||
895 | } | 884 | } |
896 | 885 | ||
897 | static const struct drm_plane_helper_funcs ade_plane_helper_funcs = { | 886 | static const struct drm_plane_helper_funcs ade_plane_helper_funcs = { |
898 | .prepare_fb = ade_plane_prepare_fb, | ||
899 | .cleanup_fb = ade_plane_cleanup_fb, | ||
900 | .atomic_check = ade_plane_atomic_check, | 887 | .atomic_check = ade_plane_atomic_check, |
901 | .atomic_update = ade_plane_atomic_update, | 888 | .atomic_update = ade_plane_atomic_update, |
902 | .atomic_disable = ade_plane_atomic_disable, | 889 | .atomic_disable = ade_plane_atomic_disable, |
diff --git a/drivers/gpu/drm/hisilicon/kirin/kirin_drm_drv.c b/drivers/gpu/drm/hisilicon/kirin/kirin_drm_drv.c index 1edd9bc80294..1fc2f502d20d 100644 --- a/drivers/gpu/drm/hisilicon/kirin/kirin_drm_drv.c +++ b/drivers/gpu/drm/hisilicon/kirin/kirin_drm_drv.c | |||
@@ -169,7 +169,7 @@ static int kirin_gem_cma_dumb_create(struct drm_file *file, | |||
169 | 169 | ||
170 | static struct drm_driver kirin_drm_driver = { | 170 | static struct drm_driver kirin_drm_driver = { |
171 | .driver_features = DRIVER_GEM | DRIVER_MODESET | DRIVER_PRIME | | 171 | .driver_features = DRIVER_GEM | DRIVER_MODESET | DRIVER_PRIME | |
172 | DRIVER_ATOMIC | DRIVER_HAVE_IRQ, | 172 | DRIVER_ATOMIC, |
173 | .fops = &kirin_drm_fops, | 173 | .fops = &kirin_drm_fops, |
174 | 174 | ||
175 | .gem_free_object_unlocked = drm_gem_cma_free_object, | 175 | .gem_free_object_unlocked = drm_gem_cma_free_object, |
diff --git a/drivers/gpu/drm/i915/i915_debugfs.c b/drivers/gpu/drm/i915/i915_debugfs.c index f62285c1ed7f..64e41cf74d11 100644 --- a/drivers/gpu/drm/i915/i915_debugfs.c +++ b/drivers/gpu/drm/i915/i915_debugfs.c | |||
@@ -3113,6 +3113,7 @@ static void intel_plane_info(struct seq_file *m, struct intel_crtc *intel_crtc) | |||
3113 | for_each_intel_plane_on_crtc(dev, intel_crtc, intel_plane) { | 3113 | for_each_intel_plane_on_crtc(dev, intel_crtc, intel_plane) { |
3114 | struct drm_plane_state *state; | 3114 | struct drm_plane_state *state; |
3115 | struct drm_plane *plane = &intel_plane->base; | 3115 | struct drm_plane *plane = &intel_plane->base; |
3116 | char *format_name; | ||
3116 | 3117 | ||
3117 | if (!plane->state) { | 3118 | if (!plane->state) { |
3118 | seq_puts(m, "plane->state is NULL!\n"); | 3119 | seq_puts(m, "plane->state is NULL!\n"); |
@@ -3121,6 +3122,12 @@ static void intel_plane_info(struct seq_file *m, struct intel_crtc *intel_crtc) | |||
3121 | 3122 | ||
3122 | state = plane->state; | 3123 | state = plane->state; |
3123 | 3124 | ||
3125 | if (state->fb) { | ||
3126 | format_name = drm_get_format_name(state->fb->pixel_format); | ||
3127 | } else { | ||
3128 | format_name = kstrdup("N/A", GFP_KERNEL); | ||
3129 | } | ||
3130 | |||
3124 | seq_printf(m, "\t--Plane id %d: type=%s, crtc_pos=%4dx%4d, crtc_size=%4dx%4d, src_pos=%d.%04ux%d.%04u, src_size=%d.%04ux%d.%04u, format=%s, rotation=%s\n", | 3131 | seq_printf(m, "\t--Plane id %d: type=%s, crtc_pos=%4dx%4d, crtc_size=%4dx%4d, src_pos=%d.%04ux%d.%04u, src_size=%d.%04ux%d.%04u, format=%s, rotation=%s\n", |
3125 | plane->base.id, | 3132 | plane->base.id, |
3126 | plane_type(intel_plane->base.type), | 3133 | plane_type(intel_plane->base.type), |
@@ -3134,8 +3141,10 @@ static void intel_plane_info(struct seq_file *m, struct intel_crtc *intel_crtc) | |||
3134 | ((state->src_w & 0xffff) * 15625) >> 10, | 3141 | ((state->src_w & 0xffff) * 15625) >> 10, |
3135 | (state->src_h >> 16), | 3142 | (state->src_h >> 16), |
3136 | ((state->src_h & 0xffff) * 15625) >> 10, | 3143 | ((state->src_h & 0xffff) * 15625) >> 10, |
3137 | state->fb ? drm_get_format_name(state->fb->pixel_format) : "N/A", | 3144 | format_name, |
3138 | plane_rotation(state->rotation)); | 3145 | plane_rotation(state->rotation)); |
3146 | |||
3147 | kfree(format_name); | ||
3139 | } | 3148 | } |
3140 | } | 3149 | } |
3141 | 3150 | ||
diff --git a/drivers/gpu/drm/i915/i915_vgpu.c b/drivers/gpu/drm/i915/i915_vgpu.c index 142bac976919..ca2e91259948 100644 --- a/drivers/gpu/drm/i915/i915_vgpu.c +++ b/drivers/gpu/drm/i915/i915_vgpu.c | |||
@@ -156,27 +156,27 @@ static int vgt_balloon_space(struct drm_mm *mm, | |||
156 | * host point of view, the graphic address space is partitioned by multiple | 156 | * host point of view, the graphic address space is partitioned by multiple |
157 | * vGPUs in different VMs. :: | 157 | * vGPUs in different VMs. :: |
158 | * | 158 | * |
159 | * vGPU1 view Host view | 159 | * vGPU1 view Host view |
160 | * 0 ------> +-----------+ +-----------+ | 160 | * 0 ------> +-----------+ +-----------+ |
161 | * ^ |###########| | vGPU3 | | 161 | * ^ |###########| | vGPU3 | |
162 | * | |###########| +-----------+ | 162 | * | |###########| +-----------+ |
163 | * | |###########| | vGPU2 | | 163 | * | |###########| | vGPU2 | |
164 | * | +-----------+ +-----------+ | 164 | * | +-----------+ +-----------+ |
165 | * mappable GM | available | ==> | vGPU1 | | 165 | * mappable GM | available | ==> | vGPU1 | |
166 | * | +-----------+ +-----------+ | 166 | * | +-----------+ +-----------+ |
167 | * | |###########| | | | 167 | * | |###########| | | |
168 | * v |###########| | Host | | 168 | * v |###########| | Host | |
169 | * +=======+===========+ +===========+ | 169 | * +=======+===========+ +===========+ |
170 | * ^ |###########| | vGPU3 | | 170 | * ^ |###########| | vGPU3 | |
171 | * | |###########| +-----------+ | 171 | * | |###########| +-----------+ |
172 | * | |###########| | vGPU2 | | 172 | * | |###########| | vGPU2 | |
173 | * | +-----------+ +-----------+ | 173 | * | +-----------+ +-----------+ |
174 | * unmappable GM | available | ==> | vGPU1 | | 174 | * unmappable GM | available | ==> | vGPU1 | |
175 | * | +-----------+ +-----------+ | 175 | * | +-----------+ +-----------+ |
176 | * | |###########| | | | 176 | * | |###########| | | |
177 | * | |###########| | Host | | 177 | * | |###########| | Host | |
178 | * v |###########| | | | 178 | * v |###########| | | |
179 | * total GM size ------> +-----------+ +-----------+ | 179 | * total GM size ------> +-----------+ +-----------+ |
180 | * | 180 | * |
181 | * Returns: | 181 | * Returns: |
182 | * zero on success, non-zero if configuration invalid or ballooning failed | 182 | * zero on success, non-zero if configuration invalid or ballooning failed |
diff --git a/drivers/gpu/drm/i915/intel_atomic_plane.c b/drivers/gpu/drm/i915/intel_atomic_plane.c index e06d1f5334cf..b82de3072d4f 100644 --- a/drivers/gpu/drm/i915/intel_atomic_plane.c +++ b/drivers/gpu/drm/i915/intel_atomic_plane.c | |||
@@ -143,6 +143,7 @@ static int intel_plane_atomic_check(struct drm_plane *plane, | |||
143 | crtc_state->base.enable ? crtc_state->pipe_src_h : 0; | 143 | crtc_state->base.enable ? crtc_state->pipe_src_h : 0; |
144 | 144 | ||
145 | if (state->fb && intel_rotation_90_or_270(state->rotation)) { | 145 | if (state->fb && intel_rotation_90_or_270(state->rotation)) { |
146 | char *format_name; | ||
146 | if (!(state->fb->modifier[0] == I915_FORMAT_MOD_Y_TILED || | 147 | if (!(state->fb->modifier[0] == I915_FORMAT_MOD_Y_TILED || |
147 | state->fb->modifier[0] == I915_FORMAT_MOD_Yf_TILED)) { | 148 | state->fb->modifier[0] == I915_FORMAT_MOD_Yf_TILED)) { |
148 | DRM_DEBUG_KMS("Y/Yf tiling required for 90/270!\n"); | 149 | DRM_DEBUG_KMS("Y/Yf tiling required for 90/270!\n"); |
@@ -157,8 +158,9 @@ static int intel_plane_atomic_check(struct drm_plane *plane, | |||
157 | switch (state->fb->pixel_format) { | 158 | switch (state->fb->pixel_format) { |
158 | case DRM_FORMAT_C8: | 159 | case DRM_FORMAT_C8: |
159 | case DRM_FORMAT_RGB565: | 160 | case DRM_FORMAT_RGB565: |
160 | DRM_DEBUG_KMS("Unsupported pixel format %s for 90/270!\n", | 161 | format_name = drm_get_format_name(state->fb->pixel_format); |
161 | drm_get_format_name(state->fb->pixel_format)); | 162 | DRM_DEBUG_KMS("Unsupported pixel format %s for 90/270!\n", format_name); |
163 | kfree(format_name); | ||
162 | return -EINVAL; | 164 | return -EINVAL; |
163 | 165 | ||
164 | default: | 166 | default: |
diff --git a/drivers/gpu/drm/i915/intel_audio.c b/drivers/gpu/drm/i915/intel_audio.c index d32f586f9c05..85389cdd0bec 100644 --- a/drivers/gpu/drm/i915/intel_audio.c +++ b/drivers/gpu/drm/i915/intel_audio.c | |||
@@ -51,10 +51,10 @@ | |||
51 | * related registers. (The notable exception is the power management, not | 51 | * related registers. (The notable exception is the power management, not |
52 | * covered here.) | 52 | * covered here.) |
53 | * | 53 | * |
54 | * The struct i915_audio_component is used to interact between the graphics | 54 | * The struct &i915_audio_component is used to interact between the graphics |
55 | * and audio drivers. The struct i915_audio_component_ops *ops in it is | 55 | * and audio drivers. The struct &i915_audio_component_ops @ops in it is |
56 | * defined in graphics driver and called in audio driver. The | 56 | * defined in graphics driver and called in audio driver. The |
57 | * struct i915_audio_component_audio_ops *audio_ops is called from i915 driver. | 57 | * struct &i915_audio_component_audio_ops @audio_ops is called from i915 driver. |
58 | */ | 58 | */ |
59 | 59 | ||
60 | static const struct { | 60 | static const struct { |
diff --git a/drivers/gpu/drm/i915/intel_display.c b/drivers/gpu/drm/i915/intel_display.c index c6f27ab99e8f..54bbb9c70a75 100644 --- a/drivers/gpu/drm/i915/intel_display.c +++ b/drivers/gpu/drm/i915/intel_display.c | |||
@@ -12258,6 +12258,7 @@ static void intel_dump_pipe_config(struct intel_crtc *crtc, | |||
12258 | 12258 | ||
12259 | DRM_DEBUG_KMS("planes on this crtc\n"); | 12259 | DRM_DEBUG_KMS("planes on this crtc\n"); |
12260 | list_for_each_entry(plane, &dev->mode_config.plane_list, head) { | 12260 | list_for_each_entry(plane, &dev->mode_config.plane_list, head) { |
12261 | char *format_name; | ||
12261 | intel_plane = to_intel_plane(plane); | 12262 | intel_plane = to_intel_plane(plane); |
12262 | if (intel_plane->pipe != crtc->pipe) | 12263 | if (intel_plane->pipe != crtc->pipe) |
12263 | continue; | 12264 | continue; |
@@ -12270,11 +12271,12 @@ static void intel_dump_pipe_config(struct intel_crtc *crtc, | |||
12270 | continue; | 12271 | continue; |
12271 | } | 12272 | } |
12272 | 12273 | ||
12274 | format_name = drm_get_format_name(fb->pixel_format); | ||
12275 | |||
12273 | DRM_DEBUG_KMS("[PLANE:%d:%s] enabled", | 12276 | DRM_DEBUG_KMS("[PLANE:%d:%s] enabled", |
12274 | plane->base.id, plane->name); | 12277 | plane->base.id, plane->name); |
12275 | DRM_DEBUG_KMS("\tFB:%d, fb = %ux%u format = %s", | 12278 | DRM_DEBUG_KMS("\tFB:%d, fb = %ux%u format = %s", |
12276 | fb->base.id, fb->width, fb->height, | 12279 | fb->base.id, fb->width, fb->height, format_name); |
12277 | drm_get_format_name(fb->pixel_format)); | ||
12278 | DRM_DEBUG_KMS("\tscaler:%d src %dx%d+%d+%d dst %dx%d+%d+%d\n", | 12280 | DRM_DEBUG_KMS("\tscaler:%d src %dx%d+%d+%d dst %dx%d+%d+%d\n", |
12279 | state->scaler_id, | 12281 | state->scaler_id, |
12280 | state->base.src.x1 >> 16, | 12282 | state->base.src.x1 >> 16, |
@@ -12284,6 +12286,8 @@ static void intel_dump_pipe_config(struct intel_crtc *crtc, | |||
12284 | state->base.dst.x1, state->base.dst.y1, | 12286 | state->base.dst.x1, state->base.dst.y1, |
12285 | drm_rect_width(&state->base.dst), | 12287 | drm_rect_width(&state->base.dst), |
12286 | drm_rect_height(&state->base.dst)); | 12288 | drm_rect_height(&state->base.dst)); |
12289 | |||
12290 | kfree(format_name); | ||
12287 | } | 12291 | } |
12288 | } | 12292 | } |
12289 | 12293 | ||
@@ -13972,7 +13976,7 @@ static const struct drm_crtc_funcs intel_crtc_funcs = { | |||
13972 | */ | 13976 | */ |
13973 | int | 13977 | int |
13974 | intel_prepare_plane_fb(struct drm_plane *plane, | 13978 | intel_prepare_plane_fb(struct drm_plane *plane, |
13975 | const struct drm_plane_state *new_state) | 13979 | struct drm_plane_state *new_state) |
13976 | { | 13980 | { |
13977 | struct drm_device *dev = plane->dev; | 13981 | struct drm_device *dev = plane->dev; |
13978 | struct drm_framebuffer *fb = new_state->fb; | 13982 | struct drm_framebuffer *fb = new_state->fb; |
@@ -14054,7 +14058,7 @@ intel_prepare_plane_fb(struct drm_plane *plane, | |||
14054 | */ | 14058 | */ |
14055 | void | 14059 | void |
14056 | intel_cleanup_plane_fb(struct drm_plane *plane, | 14060 | intel_cleanup_plane_fb(struct drm_plane *plane, |
14057 | const struct drm_plane_state *old_state) | 14061 | struct drm_plane_state *old_state) |
14058 | { | 14062 | { |
14059 | struct drm_device *dev = plane->dev; | 14063 | struct drm_device *dev = plane->dev; |
14060 | struct intel_plane_state *old_intel_state; | 14064 | struct intel_plane_state *old_intel_state; |
@@ -14911,6 +14915,7 @@ static int intel_framebuffer_init(struct drm_device *dev, | |||
14911 | unsigned int aligned_height; | 14915 | unsigned int aligned_height; |
14912 | int ret; | 14916 | int ret; |
14913 | u32 pitch_limit, stride_alignment; | 14917 | u32 pitch_limit, stride_alignment; |
14918 | char *format_name; | ||
14914 | 14919 | ||
14915 | WARN_ON(!mutex_is_locked(&dev->struct_mutex)); | 14920 | WARN_ON(!mutex_is_locked(&dev->struct_mutex)); |
14916 | 14921 | ||
@@ -14985,16 +14990,18 @@ static int intel_framebuffer_init(struct drm_device *dev, | |||
14985 | break; | 14990 | break; |
14986 | case DRM_FORMAT_XRGB1555: | 14991 | case DRM_FORMAT_XRGB1555: |
14987 | if (INTEL_INFO(dev)->gen > 3) { | 14992 | if (INTEL_INFO(dev)->gen > 3) { |
14988 | DRM_DEBUG("unsupported pixel format: %s\n", | 14993 | format_name = drm_get_format_name(mode_cmd->pixel_format); |
14989 | drm_get_format_name(mode_cmd->pixel_format)); | 14994 | DRM_DEBUG("unsupported pixel format: %s\n", format_name); |
14995 | kfree(format_name); | ||
14990 | return -EINVAL; | 14996 | return -EINVAL; |
14991 | } | 14997 | } |
14992 | break; | 14998 | break; |
14993 | case DRM_FORMAT_ABGR8888: | 14999 | case DRM_FORMAT_ABGR8888: |
14994 | if (!IS_VALLEYVIEW(dev) && !IS_CHERRYVIEW(dev) && | 15000 | if (!IS_VALLEYVIEW(dev) && !IS_CHERRYVIEW(dev) && |
14995 | INTEL_INFO(dev)->gen < 9) { | 15001 | INTEL_INFO(dev)->gen < 9) { |
14996 | DRM_DEBUG("unsupported pixel format: %s\n", | 15002 | format_name = drm_get_format_name(mode_cmd->pixel_format); |
14997 | drm_get_format_name(mode_cmd->pixel_format)); | 15003 | DRM_DEBUG("unsupported pixel format: %s\n", format_name); |
15004 | kfree(format_name); | ||
14998 | return -EINVAL; | 15005 | return -EINVAL; |
14999 | } | 15006 | } |
15000 | break; | 15007 | break; |
@@ -15002,15 +15009,17 @@ static int intel_framebuffer_init(struct drm_device *dev, | |||
15002 | case DRM_FORMAT_XRGB2101010: | 15009 | case DRM_FORMAT_XRGB2101010: |
15003 | case DRM_FORMAT_XBGR2101010: | 15010 | case DRM_FORMAT_XBGR2101010: |
15004 | if (INTEL_INFO(dev)->gen < 4) { | 15011 | if (INTEL_INFO(dev)->gen < 4) { |
15005 | DRM_DEBUG("unsupported pixel format: %s\n", | 15012 | format_name = drm_get_format_name(mode_cmd->pixel_format); |
15006 | drm_get_format_name(mode_cmd->pixel_format)); | 15013 | DRM_DEBUG("unsupported pixel format: %s\n", format_name); |
15014 | kfree(format_name); | ||
15007 | return -EINVAL; | 15015 | return -EINVAL; |
15008 | } | 15016 | } |
15009 | break; | 15017 | break; |
15010 | case DRM_FORMAT_ABGR2101010: | 15018 | case DRM_FORMAT_ABGR2101010: |
15011 | if (!IS_VALLEYVIEW(dev) && !IS_CHERRYVIEW(dev)) { | 15019 | if (!IS_VALLEYVIEW(dev) && !IS_CHERRYVIEW(dev)) { |
15012 | DRM_DEBUG("unsupported pixel format: %s\n", | 15020 | format_name = drm_get_format_name(mode_cmd->pixel_format); |
15013 | drm_get_format_name(mode_cmd->pixel_format)); | 15021 | DRM_DEBUG("unsupported pixel format: %s\n", format_name); |
15022 | kfree(format_name); | ||
15014 | return -EINVAL; | 15023 | return -EINVAL; |
15015 | } | 15024 | } |
15016 | break; | 15025 | break; |
@@ -15019,14 +15028,16 @@ static int intel_framebuffer_init(struct drm_device *dev, | |||
15019 | case DRM_FORMAT_YVYU: | 15028 | case DRM_FORMAT_YVYU: |
15020 | case DRM_FORMAT_VYUY: | 15029 | case DRM_FORMAT_VYUY: |
15021 | if (INTEL_INFO(dev)->gen < 5) { | 15030 | if (INTEL_INFO(dev)->gen < 5) { |
15022 | DRM_DEBUG("unsupported pixel format: %s\n", | 15031 | format_name = drm_get_format_name(mode_cmd->pixel_format); |
15023 | drm_get_format_name(mode_cmd->pixel_format)); | 15032 | DRM_DEBUG("unsupported pixel format: %s\n", format_name); |
15033 | kfree(format_name); | ||
15024 | return -EINVAL; | 15034 | return -EINVAL; |
15025 | } | 15035 | } |
15026 | break; | 15036 | break; |
15027 | default: | 15037 | default: |
15028 | DRM_DEBUG("unsupported pixel format: %s\n", | 15038 | format_name = drm_get_format_name(mode_cmd->pixel_format); |
15029 | drm_get_format_name(mode_cmd->pixel_format)); | 15039 | DRM_DEBUG("unsupported pixel format: %s\n", format_name); |
15040 | kfree(format_name); | ||
15030 | return -EINVAL; | 15041 | return -EINVAL; |
15031 | } | 15042 | } |
15032 | 15043 | ||
diff --git a/drivers/gpu/drm/i915/intel_drv.h b/drivers/gpu/drm/i915/intel_drv.h index c29a429cbc45..b37b8ef0c745 100644 --- a/drivers/gpu/drm/i915/intel_drv.h +++ b/drivers/gpu/drm/i915/intel_drv.h | |||
@@ -1225,9 +1225,9 @@ void intel_finish_page_flip_cs(struct drm_i915_private *dev_priv, int pipe); | |||
1225 | void intel_finish_page_flip_mmio(struct drm_i915_private *dev_priv, int pipe); | 1225 | void intel_finish_page_flip_mmio(struct drm_i915_private *dev_priv, int pipe); |
1226 | void intel_check_page_flip(struct drm_i915_private *dev_priv, int pipe); | 1226 | void intel_check_page_flip(struct drm_i915_private *dev_priv, int pipe); |
1227 | int intel_prepare_plane_fb(struct drm_plane *plane, | 1227 | int intel_prepare_plane_fb(struct drm_plane *plane, |
1228 | const struct drm_plane_state *new_state); | 1228 | struct drm_plane_state *new_state); |
1229 | void intel_cleanup_plane_fb(struct drm_plane *plane, | 1229 | void intel_cleanup_plane_fb(struct drm_plane *plane, |
1230 | const struct drm_plane_state *old_state); | 1230 | struct drm_plane_state *old_state); |
1231 | int intel_plane_atomic_get_property(struct drm_plane *plane, | 1231 | int intel_plane_atomic_get_property(struct drm_plane *plane, |
1232 | const struct drm_plane_state *state, | 1232 | const struct drm_plane_state *state, |
1233 | struct drm_property *property, | 1233 | struct drm_property *property, |
diff --git a/drivers/gpu/drm/i915/intel_guc_fwif.h b/drivers/gpu/drm/i915/intel_guc_fwif.h index 944786d7075b..e40db2d2ae99 100644 --- a/drivers/gpu/drm/i915/intel_guc_fwif.h +++ b/drivers/gpu/drm/i915/intel_guc_fwif.h | |||
@@ -155,6 +155,7 @@ | |||
155 | * | 155 | * |
156 | * +-------------------------------+ | 156 | * +-------------------------------+ |
157 | * | guc_css_header | | 157 | * | guc_css_header | |
158 | * | | | ||
158 | * | contains major/minor version | | 159 | * | contains major/minor version | |
159 | * +-------------------------------+ | 160 | * +-------------------------------+ |
160 | * | uCode | | 161 | * | uCode | |
@@ -176,10 +177,10 @@ | |||
176 | * | 177 | * |
177 | * 1. Header, uCode and RSA are must-have components. | 178 | * 1. Header, uCode and RSA are must-have components. |
178 | * 2. All firmware components, if they present, are in the sequence illustrated | 179 | * 2. All firmware components, if they present, are in the sequence illustrated |
179 | * in the layout table above. | 180 | * in the layout table above. |
180 | * 3. Length info of each component can be found in header, in dwords. | 181 | * 3. Length info of each component can be found in header, in dwords. |
181 | * 4. Modulus and exponent key are not required by driver. They may not appear | 182 | * 4. Modulus and exponent key are not required by driver. They may not appear |
182 | * in fw. So driver will load a truncated firmware in this case. | 183 | * in fw. So driver will load a truncated firmware in this case. |
183 | */ | 184 | */ |
184 | 185 | ||
185 | struct guc_css_header { | 186 | struct guc_css_header { |
diff --git a/drivers/gpu/drm/i915/intel_lvds.c b/drivers/gpu/drm/i915/intel_lvds.c index 49550470483e..e29f3d12fd1c 100644 --- a/drivers/gpu/drm/i915/intel_lvds.c +++ b/drivers/gpu/drm/i915/intel_lvds.c | |||
@@ -1054,17 +1054,6 @@ void intel_lvds_init(struct drm_device *dev) | |||
1054 | } | 1054 | } |
1055 | lvds_connector->base.edid = edid; | 1055 | lvds_connector->base.edid = edid; |
1056 | 1056 | ||
1057 | if (IS_ERR_OR_NULL(edid)) { | ||
1058 | /* Didn't get an EDID, so | ||
1059 | * Set wide sync ranges so we get all modes | ||
1060 | * handed to valid_mode for checking | ||
1061 | */ | ||
1062 | connector->display_info.min_vfreq = 0; | ||
1063 | connector->display_info.max_vfreq = 200; | ||
1064 | connector->display_info.min_hfreq = 0; | ||
1065 | connector->display_info.max_hfreq = 200; | ||
1066 | } | ||
1067 | |||
1068 | list_for_each_entry(scan, &connector->probed_modes, head) { | 1057 | list_for_each_entry(scan, &connector->probed_modes, head) { |
1069 | if (scan->type & DRM_MODE_TYPE_PREFERRED) { | 1058 | if (scan->type & DRM_MODE_TYPE_PREFERRED) { |
1070 | DRM_DEBUG_KMS("using preferred mode from EDID: "); | 1059 | DRM_DEBUG_KMS("using preferred mode from EDID: "); |
diff --git a/drivers/gpu/drm/mgag200/mgag200_fb.c b/drivers/gpu/drm/mgag200/mgag200_fb.c index 81325f64134f..88dd2214114d 100644 --- a/drivers/gpu/drm/mgag200/mgag200_fb.c +++ b/drivers/gpu/drm/mgag200/mgag200_fb.c | |||
@@ -183,8 +183,10 @@ static int mgag200fb_create(struct drm_fb_helper *helper, | |||
183 | } | 183 | } |
184 | 184 | ||
185 | sysram = vmalloc(size); | 185 | sysram = vmalloc(size); |
186 | if (!sysram) | 186 | if (!sysram) { |
187 | ret = -ENOMEM; | ||
187 | goto err_sysram; | 188 | goto err_sysram; |
189 | } | ||
188 | 190 | ||
189 | info = drm_fb_helper_alloc_fbi(helper); | 191 | info = drm_fb_helper_alloc_fbi(helper); |
190 | if (IS_ERR(info)) { | 192 | if (IS_ERR(info)) { |
diff --git a/drivers/gpu/drm/msm/mdp/mdp4/mdp4_plane.c b/drivers/gpu/drm/msm/mdp/mdp4/mdp4_plane.c index 9f96dfe67769..7c9626d92019 100644 --- a/drivers/gpu/drm/msm/mdp/mdp4/mdp4_plane.c +++ b/drivers/gpu/drm/msm/mdp/mdp4/mdp4_plane.c | |||
@@ -99,7 +99,7 @@ static const struct drm_plane_funcs mdp4_plane_funcs = { | |||
99 | }; | 99 | }; |
100 | 100 | ||
101 | static int mdp4_plane_prepare_fb(struct drm_plane *plane, | 101 | static int mdp4_plane_prepare_fb(struct drm_plane *plane, |
102 | const struct drm_plane_state *new_state) | 102 | struct drm_plane_state *new_state) |
103 | { | 103 | { |
104 | struct mdp4_plane *mdp4_plane = to_mdp4_plane(plane); | 104 | struct mdp4_plane *mdp4_plane = to_mdp4_plane(plane); |
105 | struct mdp4_kms *mdp4_kms = get_kms(plane); | 105 | struct mdp4_kms *mdp4_kms = get_kms(plane); |
@@ -113,7 +113,7 @@ static int mdp4_plane_prepare_fb(struct drm_plane *plane, | |||
113 | } | 113 | } |
114 | 114 | ||
115 | static void mdp4_plane_cleanup_fb(struct drm_plane *plane, | 115 | static void mdp4_plane_cleanup_fb(struct drm_plane *plane, |
116 | const struct drm_plane_state *old_state) | 116 | struct drm_plane_state *old_state) |
117 | { | 117 | { |
118 | struct mdp4_plane *mdp4_plane = to_mdp4_plane(plane); | 118 | struct mdp4_plane *mdp4_plane = to_mdp4_plane(plane); |
119 | struct mdp4_kms *mdp4_kms = get_kms(plane); | 119 | struct mdp4_kms *mdp4_kms = get_kms(plane); |
diff --git a/drivers/gpu/drm/msm/mdp/mdp5/mdp5_plane.c b/drivers/gpu/drm/msm/mdp/mdp5/mdp5_plane.c index a02a24e75ba6..ba8f43278a44 100644 --- a/drivers/gpu/drm/msm/mdp/mdp5/mdp5_plane.c +++ b/drivers/gpu/drm/msm/mdp/mdp5/mdp5_plane.c | |||
@@ -250,7 +250,7 @@ static const struct drm_plane_funcs mdp5_plane_funcs = { | |||
250 | }; | 250 | }; |
251 | 251 | ||
252 | static int mdp5_plane_prepare_fb(struct drm_plane *plane, | 252 | static int mdp5_plane_prepare_fb(struct drm_plane *plane, |
253 | const struct drm_plane_state *new_state) | 253 | struct drm_plane_state *new_state) |
254 | { | 254 | { |
255 | struct mdp5_plane *mdp5_plane = to_mdp5_plane(plane); | 255 | struct mdp5_plane *mdp5_plane = to_mdp5_plane(plane); |
256 | struct mdp5_kms *mdp5_kms = get_kms(plane); | 256 | struct mdp5_kms *mdp5_kms = get_kms(plane); |
@@ -264,7 +264,7 @@ static int mdp5_plane_prepare_fb(struct drm_plane *plane, | |||
264 | } | 264 | } |
265 | 265 | ||
266 | static void mdp5_plane_cleanup_fb(struct drm_plane *plane, | 266 | static void mdp5_plane_cleanup_fb(struct drm_plane *plane, |
267 | const struct drm_plane_state *old_state) | 267 | struct drm_plane_state *old_state) |
268 | { | 268 | { |
269 | struct mdp5_plane *mdp5_plane = to_mdp5_plane(plane); | 269 | struct mdp5_plane *mdp5_plane = to_mdp5_plane(plane); |
270 | struct mdp5_kms *mdp5_kms = get_kms(plane); | 270 | struct mdp5_kms *mdp5_kms = get_kms(plane); |
diff --git a/drivers/gpu/drm/omapdrm/omap_plane.c b/drivers/gpu/drm/omapdrm/omap_plane.c index 4c7727e6be7c..66ac8c40db26 100644 --- a/drivers/gpu/drm/omapdrm/omap_plane.c +++ b/drivers/gpu/drm/omapdrm/omap_plane.c | |||
@@ -60,7 +60,7 @@ to_omap_plane_state(struct drm_plane_state *state) | |||
60 | } | 60 | } |
61 | 61 | ||
62 | static int omap_plane_prepare_fb(struct drm_plane *plane, | 62 | static int omap_plane_prepare_fb(struct drm_plane *plane, |
63 | const struct drm_plane_state *new_state) | 63 | struct drm_plane_state *new_state) |
64 | { | 64 | { |
65 | if (!new_state->fb) | 65 | if (!new_state->fb) |
66 | return 0; | 66 | return 0; |
@@ -69,7 +69,7 @@ static int omap_plane_prepare_fb(struct drm_plane *plane, | |||
69 | } | 69 | } |
70 | 70 | ||
71 | static void omap_plane_cleanup_fb(struct drm_plane *plane, | 71 | static void omap_plane_cleanup_fb(struct drm_plane *plane, |
72 | const struct drm_plane_state *old_state) | 72 | struct drm_plane_state *old_state) |
73 | { | 73 | { |
74 | if (old_state->fb) | 74 | if (old_state->fb) |
75 | omap_framebuffer_unpin(old_state->fb); | 75 | omap_framebuffer_unpin(old_state->fb); |
diff --git a/drivers/gpu/drm/radeon/atombios_crtc.c b/drivers/gpu/drm/radeon/atombios_crtc.c index a97abc8af657..a89c4803aced 100644 --- a/drivers/gpu/drm/radeon/atombios_crtc.c +++ b/drivers/gpu/drm/radeon/atombios_crtc.c | |||
@@ -1154,6 +1154,7 @@ static int dce4_crtc_do_set_base(struct drm_crtc *crtc, | |||
1154 | u32 tmp, viewport_w, viewport_h; | 1154 | u32 tmp, viewport_w, viewport_h; |
1155 | int r; | 1155 | int r; |
1156 | bool bypass_lut = false; | 1156 | bool bypass_lut = false; |
1157 | char *format_name; | ||
1157 | 1158 | ||
1158 | /* no fb bound */ | 1159 | /* no fb bound */ |
1159 | if (!atomic && !crtc->primary->fb) { | 1160 | if (!atomic && !crtc->primary->fb) { |
@@ -1257,8 +1258,9 @@ static int dce4_crtc_do_set_base(struct drm_crtc *crtc, | |||
1257 | bypass_lut = true; | 1258 | bypass_lut = true; |
1258 | break; | 1259 | break; |
1259 | default: | 1260 | default: |
1260 | DRM_ERROR("Unsupported screen format %s\n", | 1261 | format_name = drm_get_format_name(target_fb->pixel_format); |
1261 | drm_get_format_name(target_fb->pixel_format)); | 1262 | DRM_ERROR("Unsupported screen format %s\n", format_name); |
1263 | kfree(format_name); | ||
1262 | return -EINVAL; | 1264 | return -EINVAL; |
1263 | } | 1265 | } |
1264 | 1266 | ||
@@ -1469,6 +1471,7 @@ static int avivo_crtc_do_set_base(struct drm_crtc *crtc, | |||
1469 | u32 viewport_w, viewport_h; | 1471 | u32 viewport_w, viewport_h; |
1470 | int r; | 1472 | int r; |
1471 | bool bypass_lut = false; | 1473 | bool bypass_lut = false; |
1474 | char *format_name; | ||
1472 | 1475 | ||
1473 | /* no fb bound */ | 1476 | /* no fb bound */ |
1474 | if (!atomic && !crtc->primary->fb) { | 1477 | if (!atomic && !crtc->primary->fb) { |
@@ -1558,8 +1561,9 @@ static int avivo_crtc_do_set_base(struct drm_crtc *crtc, | |||
1558 | bypass_lut = true; | 1561 | bypass_lut = true; |
1559 | break; | 1562 | break; |
1560 | default: | 1563 | default: |
1561 | DRM_ERROR("Unsupported screen format %s\n", | 1564 | format_name = drm_get_format_name(target_fb->pixel_format); |
1562 | drm_get_format_name(target_fb->pixel_format)); | 1565 | DRM_ERROR("Unsupported screen format %s\n", format_name); |
1566 | kfree(format_name); | ||
1563 | return -EINVAL; | 1567 | return -EINVAL; |
1564 | } | 1568 | } |
1565 | 1569 | ||
diff --git a/drivers/gpu/drm/rockchip/analogix_dp-rockchip.c b/drivers/gpu/drm/rockchip/analogix_dp-rockchip.c index 89aadbf465f8..0e63ee25bef8 100644 --- a/drivers/gpu/drm/rockchip/analogix_dp-rockchip.c +++ b/drivers/gpu/drm/rockchip/analogix_dp-rockchip.c | |||
@@ -445,7 +445,6 @@ static struct platform_driver rockchip_dp_driver = { | |||
445 | .remove = rockchip_dp_remove, | 445 | .remove = rockchip_dp_remove, |
446 | .driver = { | 446 | .driver = { |
447 | .name = "rockchip-dp", | 447 | .name = "rockchip-dp", |
448 | .owner = THIS_MODULE, | ||
449 | .pm = &rockchip_dp_pm_ops, | 448 | .pm = &rockchip_dp_pm_ops, |
450 | .of_match_table = of_match_ptr(rockchip_dp_dt_ids), | 449 | .of_match_table = of_match_ptr(rockchip_dp_dt_ids), |
451 | }, | 450 | }, |
diff --git a/drivers/gpu/drm/rockchip/rockchip_drm_vop.c b/drivers/gpu/drm/rockchip/rockchip_drm_vop.c index 31744fe99b38..efbc41ad83b6 100644 --- a/drivers/gpu/drm/rockchip/rockchip_drm_vop.c +++ b/drivers/gpu/drm/rockchip/rockchip_drm_vop.c | |||
@@ -238,7 +238,7 @@ static enum vop_data_format vop_convert_format(uint32_t format) | |||
238 | case DRM_FORMAT_NV24: | 238 | case DRM_FORMAT_NV24: |
239 | return VOP_FMT_YUV444SP; | 239 | return VOP_FMT_YUV444SP; |
240 | default: | 240 | default: |
241 | DRM_ERROR("unsupport format[%08x]\n", format); | 241 | DRM_ERROR("unsupported format[%08x]\n", format); |
242 | return -EINVAL; | 242 | return -EINVAL; |
243 | } | 243 | } |
244 | } | 244 | } |
@@ -315,7 +315,7 @@ static void scl_vop_cal_scl_fac(struct vop *vop, const struct vop_win_data *win, | |||
315 | int vskiplines = 0; | 315 | int vskiplines = 0; |
316 | 316 | ||
317 | if (dst_w > 3840) { | 317 | if (dst_w > 3840) { |
318 | DRM_ERROR("Maximum destination width (3840) exceeded\n"); | 318 | DRM_DEV_ERROR(vop->dev, "Maximum dst width (3840) exceeded\n"); |
319 | return; | 319 | return; |
320 | } | 320 | } |
321 | 321 | ||
@@ -353,11 +353,11 @@ static void scl_vop_cal_scl_fac(struct vop *vop, const struct vop_win_data *win, | |||
353 | VOP_SCL_SET_EXT(vop, win, lb_mode, lb_mode); | 353 | VOP_SCL_SET_EXT(vop, win, lb_mode, lb_mode); |
354 | if (lb_mode == LB_RGB_3840X2) { | 354 | if (lb_mode == LB_RGB_3840X2) { |
355 | if (yrgb_ver_scl_mode != SCALE_NONE) { | 355 | if (yrgb_ver_scl_mode != SCALE_NONE) { |
356 | DRM_ERROR("ERROR : not allow yrgb ver scale\n"); | 356 | DRM_DEV_ERROR(vop->dev, "not allow yrgb ver scale\n"); |
357 | return; | 357 | return; |
358 | } | 358 | } |
359 | if (cbcr_ver_scl_mode != SCALE_NONE) { | 359 | if (cbcr_ver_scl_mode != SCALE_NONE) { |
360 | DRM_ERROR("ERROR : not allow cbcr ver scale\n"); | 360 | DRM_DEV_ERROR(vop->dev, "not allow cbcr ver scale\n"); |
361 | return; | 361 | return; |
362 | } | 362 | } |
363 | vsu_mode = SCALE_UP_BIL; | 363 | vsu_mode = SCALE_UP_BIL; |
@@ -428,7 +428,7 @@ static void vop_dsp_hold_valid_irq_disable(struct vop *vop) | |||
428 | spin_unlock_irqrestore(&vop->irq_lock, flags); | 428 | spin_unlock_irqrestore(&vop->irq_lock, flags); |
429 | } | 429 | } |
430 | 430 | ||
431 | static void vop_enable(struct drm_crtc *crtc) | 431 | static int vop_enable(struct drm_crtc *crtc) |
432 | { | 432 | { |
433 | struct vop *vop = to_vop(crtc); | 433 | struct vop *vop = to_vop(crtc); |
434 | int ret; | 434 | int ret; |
@@ -436,26 +436,20 @@ static void vop_enable(struct drm_crtc *crtc) | |||
436 | ret = pm_runtime_get_sync(vop->dev); | 436 | ret = pm_runtime_get_sync(vop->dev); |
437 | if (ret < 0) { | 437 | if (ret < 0) { |
438 | dev_err(vop->dev, "failed to get pm runtime: %d\n", ret); | 438 | dev_err(vop->dev, "failed to get pm runtime: %d\n", ret); |
439 | return; | 439 | goto err_put_pm_runtime; |
440 | } | 440 | } |
441 | 441 | ||
442 | ret = clk_enable(vop->hclk); | 442 | ret = clk_enable(vop->hclk); |
443 | if (ret < 0) { | 443 | if (WARN_ON(ret < 0)) |
444 | dev_err(vop->dev, "failed to enable hclk - %d\n", ret); | 444 | goto err_put_pm_runtime; |
445 | return; | ||
446 | } | ||
447 | 445 | ||
448 | ret = clk_enable(vop->dclk); | 446 | ret = clk_enable(vop->dclk); |
449 | if (ret < 0) { | 447 | if (WARN_ON(ret < 0)) |
450 | dev_err(vop->dev, "failed to enable dclk - %d\n", ret); | ||
451 | goto err_disable_hclk; | 448 | goto err_disable_hclk; |
452 | } | ||
453 | 449 | ||
454 | ret = clk_enable(vop->aclk); | 450 | ret = clk_enable(vop->aclk); |
455 | if (ret < 0) { | 451 | if (WARN_ON(ret < 0)) |
456 | dev_err(vop->dev, "failed to enable aclk - %d\n", ret); | ||
457 | goto err_disable_dclk; | 452 | goto err_disable_dclk; |
458 | } | ||
459 | 453 | ||
460 | /* | 454 | /* |
461 | * Slave iommu shares power, irq and clock with vop. It was associated | 455 | * Slave iommu shares power, irq and clock with vop. It was associated |
@@ -485,7 +479,7 @@ static void vop_enable(struct drm_crtc *crtc) | |||
485 | 479 | ||
486 | drm_crtc_vblank_on(crtc); | 480 | drm_crtc_vblank_on(crtc); |
487 | 481 | ||
488 | return; | 482 | return 0; |
489 | 483 | ||
490 | err_disable_aclk: | 484 | err_disable_aclk: |
491 | clk_disable(vop->aclk); | 485 | clk_disable(vop->aclk); |
@@ -493,6 +487,9 @@ err_disable_dclk: | |||
493 | clk_disable(vop->dclk); | 487 | clk_disable(vop->dclk); |
494 | err_disable_hclk: | 488 | err_disable_hclk: |
495 | clk_disable(vop->hclk); | 489 | clk_disable(vop->hclk); |
490 | err_put_pm_runtime: | ||
491 | pm_runtime_put_sync(vop->dev); | ||
492 | return ret; | ||
496 | } | 493 | } |
497 | 494 | ||
498 | static void vop_crtc_disable(struct drm_crtc *crtc) | 495 | static void vop_crtc_disable(struct drm_crtc *crtc) |
@@ -567,7 +564,7 @@ static void vop_plane_destroy(struct drm_plane *plane) | |||
567 | } | 564 | } |
568 | 565 | ||
569 | static int vop_plane_prepare_fb(struct drm_plane *plane, | 566 | static int vop_plane_prepare_fb(struct drm_plane *plane, |
570 | const struct drm_plane_state *new_state) | 567 | struct drm_plane_state *new_state) |
571 | { | 568 | { |
572 | if (plane->state->fb) | 569 | if (plane->state->fb) |
573 | drm_framebuffer_reference(plane->state->fb); | 570 | drm_framebuffer_reference(plane->state->fb); |
@@ -576,7 +573,7 @@ static int vop_plane_prepare_fb(struct drm_plane *plane, | |||
576 | } | 573 | } |
577 | 574 | ||
578 | static void vop_plane_cleanup_fb(struct drm_plane *plane, | 575 | static void vop_plane_cleanup_fb(struct drm_plane *plane, |
579 | const struct drm_plane_state *old_state) | 576 | struct drm_plane_state *old_state) |
580 | { | 577 | { |
581 | if (old_state->fb) | 578 | if (old_state->fb) |
582 | drm_framebuffer_unreference(old_state->fb); | 579 | drm_framebuffer_unreference(old_state->fb); |
@@ -912,10 +909,16 @@ static void vop_crtc_enable(struct drm_crtc *crtc) | |||
912 | u16 vact_st = adjusted_mode->vtotal - adjusted_mode->vsync_start; | 909 | u16 vact_st = adjusted_mode->vtotal - adjusted_mode->vsync_start; |
913 | u16 vact_end = vact_st + vdisplay; | 910 | u16 vact_end = vact_st + vdisplay; |
914 | uint32_t val; | 911 | uint32_t val; |
912 | int ret; | ||
915 | 913 | ||
916 | WARN_ON(vop->event); | 914 | WARN_ON(vop->event); |
917 | 915 | ||
918 | vop_enable(crtc); | 916 | ret = vop_enable(crtc); |
917 | if (ret) { | ||
918 | DRM_DEV_ERROR(vop->dev, "Failed to enable vop (%d)\n", ret); | ||
919 | return; | ||
920 | } | ||
921 | |||
919 | /* | 922 | /* |
920 | * If dclk rate is zero, mean that scanout is stop, | 923 | * If dclk rate is zero, mean that scanout is stop, |
921 | * we don't need wait any more. | 924 | * we don't need wait any more. |
@@ -970,7 +973,8 @@ static void vop_crtc_enable(struct drm_crtc *crtc) | |||
970 | VOP_CTRL_SET(vop, mipi_en, 1); | 973 | VOP_CTRL_SET(vop, mipi_en, 1); |
971 | break; | 974 | break; |
972 | default: | 975 | default: |
973 | DRM_ERROR("unsupport connector_type[%d]\n", s->output_type); | 976 | DRM_DEV_ERROR(vop->dev, "unsupported connector_type [%d]\n", |
977 | s->output_type); | ||
974 | } | 978 | } |
975 | VOP_CTRL_SET(vop, out_mode, s->output_mode); | 979 | VOP_CTRL_SET(vop, out_mode, s->output_mode); |
976 | 980 | ||
@@ -1154,7 +1158,8 @@ static irqreturn_t vop_isr(int irq, void *data) | |||
1154 | 1158 | ||
1155 | /* Unhandled irqs are spurious. */ | 1159 | /* Unhandled irqs are spurious. */ |
1156 | if (active_irqs) | 1160 | if (active_irqs) |
1157 | DRM_ERROR("Unknown VOP IRQs: %#02x\n", active_irqs); | 1161 | DRM_DEV_ERROR(vop->dev, "Unknown VOP IRQs: %#02x\n", |
1162 | active_irqs); | ||
1158 | 1163 | ||
1159 | return ret; | 1164 | return ret; |
1160 | } | 1165 | } |
@@ -1189,7 +1194,8 @@ static int vop_create_crtc(struct vop *vop) | |||
1189 | win_data->phy->nformats, | 1194 | win_data->phy->nformats, |
1190 | win_data->type, NULL); | 1195 | win_data->type, NULL); |
1191 | if (ret) { | 1196 | if (ret) { |
1192 | DRM_ERROR("failed to initialize plane\n"); | 1197 | DRM_DEV_ERROR(vop->dev, "failed to init plane %d\n", |
1198 | ret); | ||
1193 | goto err_cleanup_planes; | 1199 | goto err_cleanup_planes; |
1194 | } | 1200 | } |
1195 | 1201 | ||
@@ -1227,7 +1233,8 @@ static int vop_create_crtc(struct vop *vop) | |||
1227 | win_data->phy->nformats, | 1233 | win_data->phy->nformats, |
1228 | win_data->type, NULL); | 1234 | win_data->type, NULL); |
1229 | if (ret) { | 1235 | if (ret) { |
1230 | DRM_ERROR("failed to initialize overlay plane\n"); | 1236 | DRM_DEV_ERROR(vop->dev, "failed to init overlay %d\n", |
1237 | ret); | ||
1231 | goto err_cleanup_crtc; | 1238 | goto err_cleanup_crtc; |
1232 | } | 1239 | } |
1233 | drm_plane_helper_add(&vop_win->base, &plane_helper_funcs); | 1240 | drm_plane_helper_add(&vop_win->base, &plane_helper_funcs); |
@@ -1235,8 +1242,8 @@ static int vop_create_crtc(struct vop *vop) | |||
1235 | 1242 | ||
1236 | port = of_get_child_by_name(dev->of_node, "port"); | 1243 | port = of_get_child_by_name(dev->of_node, "port"); |
1237 | if (!port) { | 1244 | if (!port) { |
1238 | DRM_ERROR("no port node found in %s\n", | 1245 | DRM_DEV_ERROR(vop->dev, "no port node found in %s\n", |
1239 | dev->of_node->full_name); | 1246 | dev->of_node->full_name); |
1240 | ret = -ENOENT; | 1247 | ret = -ENOENT; |
1241 | goto err_cleanup_crtc; | 1248 | goto err_cleanup_crtc; |
1242 | } | 1249 | } |
diff --git a/drivers/gpu/drm/rockchip/rockchip_vop_reg.c b/drivers/gpu/drm/rockchip/rockchip_vop_reg.c index 919992cdc97e..b7f59c443730 100644 --- a/drivers/gpu/drm/rockchip/rockchip_vop_reg.c +++ b/drivers/gpu/drm/rockchip/rockchip_vop_reg.c | |||
@@ -305,7 +305,6 @@ static struct platform_driver vop_platform_driver = { | |||
305 | .remove = vop_remove, | 305 | .remove = vop_remove, |
306 | .driver = { | 306 | .driver = { |
307 | .name = "rockchip-vop", | 307 | .name = "rockchip-vop", |
308 | .owner = THIS_MODULE, | ||
309 | .of_match_table = of_match_ptr(vop_driver_dt_match), | 308 | .of_match_table = of_match_ptr(vop_driver_dt_match), |
310 | }, | 309 | }, |
311 | }; | 310 | }; |
diff --git a/drivers/gpu/drm/savage/savage_state.c b/drivers/gpu/drm/savage/savage_state.c index c01ad0aeaa58..3dc0d8ff95ec 100644 --- a/drivers/gpu/drm/savage/savage_state.c +++ b/drivers/gpu/drm/savage/savage_state.c | |||
@@ -1001,15 +1001,9 @@ int savage_bci_cmdbuf(struct drm_device *dev, void *data, struct drm_file *file_ | |||
1001 | cmdbuf->cmd_addr = kcmd_addr; | 1001 | cmdbuf->cmd_addr = kcmd_addr; |
1002 | } | 1002 | } |
1003 | if (cmdbuf->vb_size) { | 1003 | if (cmdbuf->vb_size) { |
1004 | kvb_addr = kmalloc(cmdbuf->vb_size, GFP_KERNEL); | 1004 | kvb_addr = memdup_user(cmdbuf->vb_addr, cmdbuf->vb_size); |
1005 | if (kvb_addr == NULL) { | 1005 | if (IS_ERR(kvb_addr)) { |
1006 | ret = -ENOMEM; | 1006 | ret = PTR_ERR(kvb_addr); |
1007 | goto done; | ||
1008 | } | ||
1009 | |||
1010 | if (copy_from_user(kvb_addr, cmdbuf->vb_addr, | ||
1011 | cmdbuf->vb_size)) { | ||
1012 | ret = -EFAULT; | ||
1013 | goto done; | 1007 | goto done; |
1014 | } | 1008 | } |
1015 | cmdbuf->vb_addr = kvb_addr; | 1009 | cmdbuf->vb_addr = kvb_addr; |
diff --git a/drivers/gpu/drm/sti/sti_drv.c b/drivers/gpu/drm/sti/sti_drv.c index 96bd3d08b2d4..f8311b2bc84e 100644 --- a/drivers/gpu/drm/sti/sti_drv.c +++ b/drivers/gpu/drm/sti/sti_drv.c | |||
@@ -282,7 +282,7 @@ static const struct file_operations sti_driver_fops = { | |||
282 | }; | 282 | }; |
283 | 283 | ||
284 | static struct drm_driver sti_driver = { | 284 | static struct drm_driver sti_driver = { |
285 | .driver_features = DRIVER_HAVE_IRQ | DRIVER_MODESET | | 285 | .driver_features = DRIVER_MODESET | |
286 | DRIVER_GEM | DRIVER_PRIME | DRIVER_ATOMIC, | 286 | DRIVER_GEM | DRIVER_PRIME | DRIVER_ATOMIC, |
287 | .gem_free_object_unlocked = drm_gem_cma_free_object, | 287 | .gem_free_object_unlocked = drm_gem_cma_free_object, |
288 | .gem_vm_ops = &drm_gem_cma_vm_ops, | 288 | .gem_vm_ops = &drm_gem_cma_vm_ops, |
diff --git a/drivers/gpu/drm/tegra/dc.c b/drivers/gpu/drm/tegra/dc.c index 8495bd01b544..3de7ce33d3d4 100644 --- a/drivers/gpu/drm/tegra/dc.c +++ b/drivers/gpu/drm/tegra/dc.c | |||
@@ -480,17 +480,6 @@ static const struct drm_plane_funcs tegra_primary_plane_funcs = { | |||
480 | .atomic_destroy_state = tegra_plane_atomic_destroy_state, | 480 | .atomic_destroy_state = tegra_plane_atomic_destroy_state, |
481 | }; | 481 | }; |
482 | 482 | ||
483 | static int tegra_plane_prepare_fb(struct drm_plane *plane, | ||
484 | const struct drm_plane_state *new_state) | ||
485 | { | ||
486 | return 0; | ||
487 | } | ||
488 | |||
489 | static void tegra_plane_cleanup_fb(struct drm_plane *plane, | ||
490 | const struct drm_plane_state *old_fb) | ||
491 | { | ||
492 | } | ||
493 | |||
494 | static int tegra_plane_state_add(struct tegra_plane *plane, | 483 | static int tegra_plane_state_add(struct tegra_plane *plane, |
495 | struct drm_plane_state *state) | 484 | struct drm_plane_state *state) |
496 | { | 485 | { |
@@ -624,8 +613,6 @@ static void tegra_plane_atomic_disable(struct drm_plane *plane, | |||
624 | } | 613 | } |
625 | 614 | ||
626 | static const struct drm_plane_helper_funcs tegra_primary_plane_helper_funcs = { | 615 | static const struct drm_plane_helper_funcs tegra_primary_plane_helper_funcs = { |
627 | .prepare_fb = tegra_plane_prepare_fb, | ||
628 | .cleanup_fb = tegra_plane_cleanup_fb, | ||
629 | .atomic_check = tegra_plane_atomic_check, | 616 | .atomic_check = tegra_plane_atomic_check, |
630 | .atomic_update = tegra_plane_atomic_update, | 617 | .atomic_update = tegra_plane_atomic_update, |
631 | .atomic_disable = tegra_plane_atomic_disable, | 618 | .atomic_disable = tegra_plane_atomic_disable, |
@@ -796,8 +783,6 @@ static const struct drm_plane_funcs tegra_cursor_plane_funcs = { | |||
796 | }; | 783 | }; |
797 | 784 | ||
798 | static const struct drm_plane_helper_funcs tegra_cursor_plane_helper_funcs = { | 785 | static const struct drm_plane_helper_funcs tegra_cursor_plane_helper_funcs = { |
799 | .prepare_fb = tegra_plane_prepare_fb, | ||
800 | .cleanup_fb = tegra_plane_cleanup_fb, | ||
801 | .atomic_check = tegra_cursor_atomic_check, | 786 | .atomic_check = tegra_cursor_atomic_check, |
802 | .atomic_update = tegra_cursor_atomic_update, | 787 | .atomic_update = tegra_cursor_atomic_update, |
803 | .atomic_disable = tegra_cursor_atomic_disable, | 788 | .atomic_disable = tegra_cursor_atomic_disable, |
@@ -866,8 +851,6 @@ static const uint32_t tegra_overlay_plane_formats[] = { | |||
866 | }; | 851 | }; |
867 | 852 | ||
868 | static const struct drm_plane_helper_funcs tegra_overlay_plane_helper_funcs = { | 853 | static const struct drm_plane_helper_funcs tegra_overlay_plane_helper_funcs = { |
869 | .prepare_fb = tegra_plane_prepare_fb, | ||
870 | .cleanup_fb = tegra_plane_cleanup_fb, | ||
871 | .atomic_check = tegra_plane_atomic_check, | 854 | .atomic_check = tegra_plane_atomic_check, |
872 | .atomic_update = tegra_plane_atomic_update, | 855 | .atomic_update = tegra_plane_atomic_update, |
873 | .atomic_disable = tegra_plane_atomic_disable, | 856 | .atomic_disable = tegra_plane_atomic_disable, |
diff --git a/drivers/gpu/drm/udl/udl_connector.c b/drivers/gpu/drm/udl/udl_connector.c index 4709b54c204c..d2f57c52f7db 100644 --- a/drivers/gpu/drm/udl/udl_connector.c +++ b/drivers/gpu/drm/udl/udl_connector.c | |||
@@ -150,8 +150,5 @@ int udl_connector_init(struct drm_device *dev, struct drm_encoder *encoder) | |||
150 | drm_connector_register(connector); | 150 | drm_connector_register(connector); |
151 | drm_mode_connector_attach_encoder(connector, encoder); | 151 | drm_mode_connector_attach_encoder(connector, encoder); |
152 | 152 | ||
153 | drm_object_attach_property(&connector->base, | ||
154 | dev->mode_config.dirty_info_property, | ||
155 | 1); | ||
156 | return 0; | 153 | return 0; |
157 | } | 154 | } |
diff --git a/drivers/gpu/drm/udl/udl_main.c b/drivers/gpu/drm/udl/udl_main.c index 33dbfb2c4748..29f0207fa677 100644 --- a/drivers/gpu/drm/udl/udl_main.c +++ b/drivers/gpu/drm/udl/udl_main.c | |||
@@ -16,6 +16,8 @@ | |||
16 | /* -BULK_SIZE as per usb-skeleton. Can we get full page and avoid overhead? */ | 16 | /* -BULK_SIZE as per usb-skeleton. Can we get full page and avoid overhead? */ |
17 | #define BULK_SIZE 512 | 17 | #define BULK_SIZE 512 |
18 | 18 | ||
19 | #define NR_USB_REQUEST_CHANNEL 0x12 | ||
20 | |||
19 | #define MAX_TRANSFER (PAGE_SIZE*16 - BULK_SIZE) | 21 | #define MAX_TRANSFER (PAGE_SIZE*16 - BULK_SIZE) |
20 | #define WRITES_IN_FLIGHT (4) | 22 | #define WRITES_IN_FLIGHT (4) |
21 | #define MAX_VENDOR_DESCRIPTOR_SIZE 256 | 23 | #define MAX_VENDOR_DESCRIPTOR_SIZE 256 |
@@ -90,6 +92,26 @@ success: | |||
90 | return true; | 92 | return true; |
91 | } | 93 | } |
92 | 94 | ||
95 | /* | ||
96 | * Need to ensure a channel is selected before submitting URBs | ||
97 | */ | ||
98 | static int udl_select_std_channel(struct udl_device *udl) | ||
99 | { | ||
100 | int ret; | ||
101 | u8 set_def_chn[] = {0x57, 0xCD, 0xDC, 0xA7, | ||
102 | 0x1C, 0x88, 0x5E, 0x15, | ||
103 | 0x60, 0xFE, 0xC6, 0x97, | ||
104 | 0x16, 0x3D, 0x47, 0xF2}; | ||
105 | |||
106 | ret = usb_control_msg(udl->udev, | ||
107 | usb_sndctrlpipe(udl->udev, 0), | ||
108 | NR_USB_REQUEST_CHANNEL, | ||
109 | (USB_DIR_OUT | USB_TYPE_VENDOR), 0, 0, | ||
110 | set_def_chn, sizeof(set_def_chn), | ||
111 | USB_CTRL_SET_TIMEOUT); | ||
112 | return ret < 0 ? ret : 0; | ||
113 | } | ||
114 | |||
93 | static void udl_release_urb_work(struct work_struct *work) | 115 | static void udl_release_urb_work(struct work_struct *work) |
94 | { | 116 | { |
95 | struct urb_node *unode = container_of(work, struct urb_node, | 117 | struct urb_node *unode = container_of(work, struct urb_node, |
@@ -301,6 +323,9 @@ int udl_driver_load(struct drm_device *dev, unsigned long flags) | |||
301 | goto err; | 323 | goto err; |
302 | } | 324 | } |
303 | 325 | ||
326 | if (udl_select_std_channel(udl)) | ||
327 | DRM_ERROR("Selecting channel failed\n"); | ||
328 | |||
304 | if (!udl_alloc_urb_list(dev, WRITES_IN_FLIGHT, MAX_TRANSFER)) { | 329 | if (!udl_alloc_urb_list(dev, WRITES_IN_FLIGHT, MAX_TRANSFER)) { |
305 | DRM_ERROR("udl_alloc_urb_list failed\n"); | 330 | DRM_ERROR("udl_alloc_urb_list failed\n"); |
306 | goto err; | 331 | goto err; |
diff --git a/drivers/gpu/drm/udl/udl_modeset.c b/drivers/gpu/drm/udl/udl_modeset.c index f92ea9579674..73695127c573 100644 --- a/drivers/gpu/drm/udl/udl_modeset.c +++ b/drivers/gpu/drm/udl/udl_modeset.c | |||
@@ -441,8 +441,6 @@ int udl_modeset_init(struct drm_device *dev) | |||
441 | 441 | ||
442 | dev->mode_config.funcs = &udl_mode_funcs; | 442 | dev->mode_config.funcs = &udl_mode_funcs; |
443 | 443 | ||
444 | drm_mode_create_dirty_info_property(dev); | ||
445 | |||
446 | udl_crtc_init(dev); | 444 | udl_crtc_init(dev); |
447 | 445 | ||
448 | encoder = udl_encoder_init(dev); | 446 | encoder = udl_encoder_init(dev); |
diff --git a/drivers/gpu/drm/vc4/vc4_plane.c b/drivers/gpu/drm/vc4/vc4_plane.c index 29e4b400e25e..881bf489478b 100644 --- a/drivers/gpu/drm/vc4/vc4_plane.c +++ b/drivers/gpu/drm/vc4/vc4_plane.c | |||
@@ -735,8 +735,6 @@ void vc4_plane_async_set_fb(struct drm_plane *plane, struct drm_framebuffer *fb) | |||
735 | } | 735 | } |
736 | 736 | ||
737 | static const struct drm_plane_helper_funcs vc4_plane_helper_funcs = { | 737 | static const struct drm_plane_helper_funcs vc4_plane_helper_funcs = { |
738 | .prepare_fb = NULL, | ||
739 | .cleanup_fb = NULL, | ||
740 | .atomic_check = vc4_plane_atomic_check, | 738 | .atomic_check = vc4_plane_atomic_check, |
741 | .atomic_update = vc4_plane_atomic_update, | 739 | .atomic_update = vc4_plane_atomic_update, |
742 | }; | 740 | }; |
diff --git a/drivers/gpu/drm/virtio/virtgpu_ioctl.c b/drivers/gpu/drm/virtio/virtgpu_ioctl.c index c046903cb47b..512e7cddcbae 100644 --- a/drivers/gpu/drm/virtio/virtgpu_ioctl.c +++ b/drivers/gpu/drm/virtio/virtgpu_ioctl.c | |||
@@ -152,15 +152,10 @@ static int virtio_gpu_execbuffer(struct drm_device *dev, | |||
152 | if (ret) | 152 | if (ret) |
153 | goto out_free; | 153 | goto out_free; |
154 | 154 | ||
155 | buf = kmalloc(exbuf->size, GFP_KERNEL); | 155 | buf = memdup_user((void __user *)(uintptr_t)exbuf->command, |
156 | if (!buf) { | 156 | exbuf->size); |
157 | ret = -ENOMEM; | 157 | if (IS_ERR(buf)) { |
158 | goto out_unresv; | 158 | ret = PTR_ERR(buf); |
159 | } | ||
160 | if (copy_from_user(buf, (void __user *)(uintptr_t)exbuf->command, | ||
161 | exbuf->size)) { | ||
162 | kfree(buf); | ||
163 | ret = -EFAULT; | ||
164 | goto out_unresv; | 159 | goto out_unresv; |
165 | } | 160 | } |
166 | virtio_gpu_cmd_submit(vgdev, buf, exbuf->size, | 161 | virtio_gpu_cmd_submit(vgdev, buf, exbuf->size, |
diff --git a/drivers/gpu/drm/vmwgfx/vmwgfx_ldu.c b/drivers/gpu/drm/vmwgfx/vmwgfx_ldu.c index 63ccd9871ec9..23ec673d5e16 100644 --- a/drivers/gpu/drm/vmwgfx/vmwgfx_ldu.c +++ b/drivers/gpu/drm/vmwgfx/vmwgfx_ldu.c | |||
@@ -377,9 +377,6 @@ static int vmw_ldu_init(struct vmw_private *dev_priv, unsigned unit) | |||
377 | drm_mode_crtc_set_gamma_size(crtc, 256); | 377 | drm_mode_crtc_set_gamma_size(crtc, 256); |
378 | 378 | ||
379 | drm_object_attach_property(&connector->base, | 379 | drm_object_attach_property(&connector->base, |
380 | dev->mode_config.dirty_info_property, | ||
381 | 1); | ||
382 | drm_object_attach_property(&connector->base, | ||
383 | dev_priv->hotplug_mode_update_property, 1); | 380 | dev_priv->hotplug_mode_update_property, 1); |
384 | drm_object_attach_property(&connector->base, | 381 | drm_object_attach_property(&connector->base, |
385 | dev->mode_config.suggested_x_property, 0); | 382 | dev->mode_config.suggested_x_property, 0); |
@@ -421,10 +418,6 @@ int vmw_kms_ldu_init_display(struct vmw_private *dev_priv) | |||
421 | if (ret != 0) | 418 | if (ret != 0) |
422 | goto err_free; | 419 | goto err_free; |
423 | 420 | ||
424 | ret = drm_mode_create_dirty_info_property(dev); | ||
425 | if (ret != 0) | ||
426 | goto err_vblank_cleanup; | ||
427 | |||
428 | vmw_kms_create_implicit_placement_property(dev_priv, true); | 421 | vmw_kms_create_implicit_placement_property(dev_priv, true); |
429 | 422 | ||
430 | if (dev_priv->capabilities & SVGA_CAP_MULTIMON) | 423 | if (dev_priv->capabilities & SVGA_CAP_MULTIMON) |
@@ -439,8 +432,6 @@ int vmw_kms_ldu_init_display(struct vmw_private *dev_priv) | |||
439 | 432 | ||
440 | return 0; | 433 | return 0; |
441 | 434 | ||
442 | err_vblank_cleanup: | ||
443 | drm_vblank_cleanup(dev); | ||
444 | err_free: | 435 | err_free: |
445 | kfree(dev_priv->ldu_priv); | 436 | kfree(dev_priv->ldu_priv); |
446 | dev_priv->ldu_priv = NULL; | 437 | dev_priv->ldu_priv = NULL; |
diff --git a/drivers/gpu/drm/vmwgfx/vmwgfx_scrn.c b/drivers/gpu/drm/vmwgfx/vmwgfx_scrn.c index b74eae2b8594..f42359084adc 100644 --- a/drivers/gpu/drm/vmwgfx/vmwgfx_scrn.c +++ b/drivers/gpu/drm/vmwgfx/vmwgfx_scrn.c | |||
@@ -538,9 +538,6 @@ static int vmw_sou_init(struct vmw_private *dev_priv, unsigned unit) | |||
538 | drm_mode_crtc_set_gamma_size(crtc, 256); | 538 | drm_mode_crtc_set_gamma_size(crtc, 256); |
539 | 539 | ||
540 | drm_object_attach_property(&connector->base, | 540 | drm_object_attach_property(&connector->base, |
541 | dev->mode_config.dirty_info_property, | ||
542 | 1); | ||
543 | drm_object_attach_property(&connector->base, | ||
544 | dev_priv->hotplug_mode_update_property, 1); | 541 | dev_priv->hotplug_mode_update_property, 1); |
545 | drm_object_attach_property(&connector->base, | 542 | drm_object_attach_property(&connector->base, |
546 | dev->mode_config.suggested_x_property, 0); | 543 | dev->mode_config.suggested_x_property, 0); |
@@ -574,10 +571,6 @@ int vmw_kms_sou_init_display(struct vmw_private *dev_priv) | |||
574 | if (unlikely(ret != 0)) | 571 | if (unlikely(ret != 0)) |
575 | return ret; | 572 | return ret; |
576 | 573 | ||
577 | ret = drm_mode_create_dirty_info_property(dev); | ||
578 | if (unlikely(ret != 0)) | ||
579 | goto err_vblank_cleanup; | ||
580 | |||
581 | vmw_kms_create_implicit_placement_property(dev_priv, false); | 574 | vmw_kms_create_implicit_placement_property(dev_priv, false); |
582 | 575 | ||
583 | for (i = 0; i < VMWGFX_NUM_DISPLAY_UNITS; ++i) | 576 | for (i = 0; i < VMWGFX_NUM_DISPLAY_UNITS; ++i) |
@@ -588,10 +581,6 @@ int vmw_kms_sou_init_display(struct vmw_private *dev_priv) | |||
588 | DRM_INFO("Screen Objects Display Unit initialized\n"); | 581 | DRM_INFO("Screen Objects Display Unit initialized\n"); |
589 | 582 | ||
590 | return 0; | 583 | return 0; |
591 | |||
592 | err_vblank_cleanup: | ||
593 | drm_vblank_cleanup(dev); | ||
594 | return ret; | ||
595 | } | 584 | } |
596 | 585 | ||
597 | int vmw_kms_sou_close_display(struct vmw_private *dev_priv) | 586 | int vmw_kms_sou_close_display(struct vmw_private *dev_priv) |
diff --git a/drivers/gpu/drm/vmwgfx/vmwgfx_stdu.c b/drivers/gpu/drm/vmwgfx/vmwgfx_stdu.c index 41932a7c4f79..94ad8d2acf9a 100644 --- a/drivers/gpu/drm/vmwgfx/vmwgfx_stdu.c +++ b/drivers/gpu/drm/vmwgfx/vmwgfx_stdu.c | |||
@@ -1131,9 +1131,6 @@ static int vmw_stdu_init(struct vmw_private *dev_priv, unsigned unit) | |||
1131 | drm_mode_crtc_set_gamma_size(crtc, 256); | 1131 | drm_mode_crtc_set_gamma_size(crtc, 256); |
1132 | 1132 | ||
1133 | drm_object_attach_property(&connector->base, | 1133 | drm_object_attach_property(&connector->base, |
1134 | dev->mode_config.dirty_info_property, | ||
1135 | 1); | ||
1136 | drm_object_attach_property(&connector->base, | ||
1137 | dev_priv->hotplug_mode_update_property, 1); | 1134 | dev_priv->hotplug_mode_update_property, 1); |
1138 | drm_object_attach_property(&connector->base, | 1135 | drm_object_attach_property(&connector->base, |
1139 | dev->mode_config.suggested_x_property, 0); | 1136 | dev->mode_config.suggested_x_property, 0); |
@@ -1202,10 +1199,6 @@ int vmw_kms_stdu_init_display(struct vmw_private *dev_priv) | |||
1202 | if (unlikely(ret != 0)) | 1199 | if (unlikely(ret != 0)) |
1203 | return ret; | 1200 | return ret; |
1204 | 1201 | ||
1205 | ret = drm_mode_create_dirty_info_property(dev); | ||
1206 | if (unlikely(ret != 0)) | ||
1207 | goto err_vblank_cleanup; | ||
1208 | |||
1209 | dev_priv->active_display_unit = vmw_du_screen_target; | 1202 | dev_priv->active_display_unit = vmw_du_screen_target; |
1210 | 1203 | ||
1211 | vmw_kms_create_implicit_placement_property(dev_priv, false); | 1204 | vmw_kms_create_implicit_placement_property(dev_priv, false); |
diff --git a/drivers/gpu/vga/vgaarb.c b/drivers/gpu/vga/vgaarb.c index f17cb0431833..1887f199ccb7 100644 --- a/drivers/gpu/vga/vgaarb.c +++ b/drivers/gpu/vga/vgaarb.c | |||
@@ -131,7 +131,24 @@ static struct vga_device *vgadev_find(struct pci_dev *pdev) | |||
131 | return NULL; | 131 | return NULL; |
132 | } | 132 | } |
133 | 133 | ||
134 | /* Returns the default VGA device (vgacon's babe) */ | 134 | /** |
135 | * vga_default_device - return the default VGA device, for vgacon | ||
136 | * | ||
137 | * This can be defined by the platform. The default implementation | ||
138 | * is rather dumb and will probably only work properly on single | ||
139 | * vga card setups and/or x86 platforms. | ||
140 | * | ||
141 | * If your VGA default device is not PCI, you'll have to return | ||
142 | * NULL here. In this case, I assume it will not conflict with | ||
143 | * any PCI card. If this is not true, I'll have to define two archs | ||
144 | * hooks for enabling/disabling the VGA default device if that is | ||
145 | * possible. This may be a problem with real _ISA_ VGA cards, in | ||
146 | * addition to a PCI one. I don't know at this point how to deal | ||
147 | * with that card. Can theirs IOs be disabled at all ? If not, then | ||
148 | * I suppose it's a matter of having the proper arch hook telling | ||
149 | * us about it, so we basically never allow anybody to succeed a | ||
150 | * vga_get()... | ||
151 | */ | ||
135 | struct pci_dev *vga_default_device(void) | 152 | struct pci_dev *vga_default_device(void) |
136 | { | 153 | { |
137 | return vga_default; | 154 | return vga_default; |
@@ -356,6 +373,40 @@ static void __vga_put(struct vga_device *vgadev, unsigned int rsrc) | |||
356 | wake_up_all(&vga_wait_queue); | 373 | wake_up_all(&vga_wait_queue); |
357 | } | 374 | } |
358 | 375 | ||
376 | /** | ||
377 | * vga_get - acquire & locks VGA resources | ||
378 | * @pdev: pci device of the VGA card or NULL for the system default | ||
379 | * @rsrc: bit mask of resources to acquire and lock | ||
380 | * @interruptible: blocking should be interruptible by signals ? | ||
381 | * | ||
382 | * This function acquires VGA resources for the given card and mark those | ||
383 | * resources locked. If the resource requested are "normal" (and not legacy) | ||
384 | * resources, the arbiter will first check whether the card is doing legacy | ||
385 | * decoding for that type of resource. If yes, the lock is "converted" into a | ||
386 | * legacy resource lock. | ||
387 | * | ||
388 | * The arbiter will first look for all VGA cards that might conflict and disable | ||
389 | * their IOs and/or Memory access, including VGA forwarding on P2P bridges if | ||
390 | * necessary, so that the requested resources can be used. Then, the card is | ||
391 | * marked as locking these resources and the IO and/or Memory accesses are | ||
392 | * enabled on the card (including VGA forwarding on parent P2P bridges if any). | ||
393 | * | ||
394 | * This function will block if some conflicting card is already locking one of | ||
395 | * the required resources (or any resource on a different bus segment, since P2P | ||
396 | * bridges don't differentiate VGA memory and IO afaik). You can indicate | ||
397 | * whether this blocking should be interruptible by a signal (for userland | ||
398 | * interface) or not. | ||
399 | * | ||
400 | * Must not be called at interrupt time or in atomic context. If the card | ||
401 | * already owns the resources, the function succeeds. Nested calls are | ||
402 | * supported (a per-resource counter is maintained) | ||
403 | * | ||
404 | * On success, release the VGA resource again with vga_put(). | ||
405 | * | ||
406 | * Returns: | ||
407 | * | ||
408 | * 0 on success, negative error code on failure. | ||
409 | */ | ||
359 | int vga_get(struct pci_dev *pdev, unsigned int rsrc, int interruptible) | 410 | int vga_get(struct pci_dev *pdev, unsigned int rsrc, int interruptible) |
360 | { | 411 | { |
361 | struct vga_device *vgadev, *conflict; | 412 | struct vga_device *vgadev, *conflict; |
@@ -408,6 +459,21 @@ int vga_get(struct pci_dev *pdev, unsigned int rsrc, int interruptible) | |||
408 | } | 459 | } |
409 | EXPORT_SYMBOL(vga_get); | 460 | EXPORT_SYMBOL(vga_get); |
410 | 461 | ||
462 | /** | ||
463 | * vga_tryget - try to acquire & lock legacy VGA resources | ||
464 | * @pdev: pci devivce of VGA card or NULL for system default | ||
465 | * @rsrc: bit mask of resources to acquire and lock | ||
466 | * | ||
467 | * This function performs the same operation as vga_get(), but will return an | ||
468 | * error (-EBUSY) instead of blocking if the resources are already locked by | ||
469 | * another card. It can be called in any context | ||
470 | * | ||
471 | * On success, release the VGA resource again with vga_put(). | ||
472 | * | ||
473 | * Returns: | ||
474 | * | ||
475 | * 0 on success, negative error code on failure. | ||
476 | */ | ||
411 | int vga_tryget(struct pci_dev *pdev, unsigned int rsrc) | 477 | int vga_tryget(struct pci_dev *pdev, unsigned int rsrc) |
412 | { | 478 | { |
413 | struct vga_device *vgadev; | 479 | struct vga_device *vgadev; |
@@ -435,6 +501,16 @@ bail: | |||
435 | } | 501 | } |
436 | EXPORT_SYMBOL(vga_tryget); | 502 | EXPORT_SYMBOL(vga_tryget); |
437 | 503 | ||
504 | /** | ||
505 | * vga_put - release lock on legacy VGA resources | ||
506 | * @pdev: pci device of VGA card or NULL for system default | ||
507 | * @rsrc: but mask of resource to release | ||
508 | * | ||
509 | * This fuction releases resources previously locked by vga_get() or | ||
510 | * vga_tryget(). The resources aren't disabled right away, so that a subsequence | ||
511 | * vga_get() on the same card will succeed immediately. Resources have a | ||
512 | * counter, so locks are only released if the counter reaches 0. | ||
513 | */ | ||
438 | void vga_put(struct pci_dev *pdev, unsigned int rsrc) | 514 | void vga_put(struct pci_dev *pdev, unsigned int rsrc) |
439 | { | 515 | { |
440 | struct vga_device *vgadev; | 516 | struct vga_device *vgadev; |
@@ -716,7 +792,37 @@ void vga_set_legacy_decoding(struct pci_dev *pdev, unsigned int decodes) | |||
716 | } | 792 | } |
717 | EXPORT_SYMBOL(vga_set_legacy_decoding); | 793 | EXPORT_SYMBOL(vga_set_legacy_decoding); |
718 | 794 | ||
719 | /* call with NULL to unregister */ | 795 | /** |
796 | * vga_client_register - register or unregister a VGA arbitration client | ||
797 | * @pdev: pci device of the VGA client | ||
798 | * @cookie: client cookie to be used in callbacks | ||
799 | * @irq_set_state: irq state change callback | ||
800 | * @set_vga_decode: vga decode change callback | ||
801 | * | ||
802 | * Clients have two callback mechanisms they can use. | ||
803 | * | ||
804 | * @irq_set_state callback: If a client can't disable its GPUs VGA | ||
805 | * resources, then we need to be able to ask it to turn off its irqs when we | ||
806 | * turn off its mem and io decoding. | ||
807 | * | ||
808 | * @set_vga_decode callback: If a client can disable its GPU VGA resource, it | ||
809 | * will get a callback from this to set the encode/decode state. | ||
810 | * | ||
811 | * Rationale: we cannot disable VGA decode resources unconditionally some single | ||
812 | * GPU laptops seem to require ACPI or BIOS access to the VGA registers to | ||
813 | * control things like backlights etc. Hopefully newer multi-GPU laptops do | ||
814 | * something saner, and desktops won't have any special ACPI for this. The | ||
815 | * driver will get a callback when VGA arbitration is first used by userspace | ||
816 | * since some older X servers have issues. | ||
817 | * | ||
818 | * This function does not check whether a client for @pdev has been registered | ||
819 | * already. | ||
820 | * | ||
821 | * To unregister just call this function with @irq_set_state and @set_vga_decode | ||
822 | * both set to NULL for the same @pdev as originally used to register them. | ||
823 | * | ||
824 | * Returns: 0 on success, -1 on failure | ||
825 | */ | ||
720 | int vga_client_register(struct pci_dev *pdev, void *cookie, | 826 | int vga_client_register(struct pci_dev *pdev, void *cookie, |
721 | void (*irq_set_state)(void *cookie, bool state), | 827 | void (*irq_set_state)(void *cookie, bool state), |
722 | unsigned int (*set_vga_decode)(void *cookie, | 828 | unsigned int (*set_vga_decode)(void *cookie, |
diff --git a/include/drm/drmP.h b/include/drm/drmP.h index f8e87fde611b..94eb138753a9 100644 --- a/include/drm/drmP.h +++ b/include/drm/drmP.h | |||
@@ -127,6 +127,7 @@ struct dma_buf_attachment; | |||
127 | * run-time by echoing the debug value in its sysfs node: | 127 | * run-time by echoing the debug value in its sysfs node: |
128 | * # echo 0xf > /sys/module/drm/parameters/debug | 128 | * # echo 0xf > /sys/module/drm/parameters/debug |
129 | */ | 129 | */ |
130 | #define DRM_UT_NONE 0x00 | ||
130 | #define DRM_UT_CORE 0x01 | 131 | #define DRM_UT_CORE 0x01 |
131 | #define DRM_UT_DRIVER 0x02 | 132 | #define DRM_UT_DRIVER 0x02 |
132 | #define DRM_UT_KMS 0x04 | 133 | #define DRM_UT_KMS 0x04 |
@@ -134,11 +135,15 @@ struct dma_buf_attachment; | |||
134 | #define DRM_UT_ATOMIC 0x10 | 135 | #define DRM_UT_ATOMIC 0x10 |
135 | #define DRM_UT_VBL 0x20 | 136 | #define DRM_UT_VBL 0x20 |
136 | 137 | ||
137 | extern __printf(2, 3) | 138 | extern __printf(6, 7) |
138 | void drm_ut_debug_printk(const char *function_name, | 139 | void drm_dev_printk(const struct device *dev, const char *level, |
139 | const char *format, ...); | 140 | unsigned int category, const char *function_name, |
140 | extern __printf(1, 2) | 141 | const char *prefix, const char *format, ...); |
141 | void drm_err(const char *format, ...); | 142 | |
143 | extern __printf(5, 6) | ||
144 | void drm_printk(const char *level, unsigned int category, | ||
145 | const char *function_name, const char *prefix, | ||
146 | const char *format, ...); | ||
142 | 147 | ||
143 | /***********************************************************************/ | 148 | /***********************************************************************/ |
144 | /** \name DRM template customization defaults */ | 149 | /** \name DRM template customization defaults */ |
@@ -169,8 +174,12 @@ void drm_err(const char *format, ...); | |||
169 | * \param fmt printf() like format string. | 174 | * \param fmt printf() like format string. |
170 | * \param arg arguments | 175 | * \param arg arguments |
171 | */ | 176 | */ |
172 | #define DRM_ERROR(fmt, ...) \ | 177 | #define DRM_DEV_ERROR(dev, fmt, ...) \ |
173 | drm_err(fmt, ##__VA_ARGS__) | 178 | drm_dev_printk(dev, KERN_ERR, DRM_UT_NONE, __func__, " *ERROR*",\ |
179 | fmt, ##__VA_ARGS__) | ||
180 | #define DRM_ERROR(fmt, ...) \ | ||
181 | drm_printk(KERN_ERR, DRM_UT_NONE, __func__, " *ERROR*", fmt, \ | ||
182 | ##__VA_ARGS__) | ||
174 | 183 | ||
175 | /** | 184 | /** |
176 | * Rate limited error output. Like DRM_ERROR() but won't flood the log. | 185 | * Rate limited error output. Like DRM_ERROR() but won't flood the log. |
@@ -178,21 +187,33 @@ void drm_err(const char *format, ...); | |||
178 | * \param fmt printf() like format string. | 187 | * \param fmt printf() like format string. |
179 | * \param arg arguments | 188 | * \param arg arguments |
180 | */ | 189 | */ |
181 | #define DRM_ERROR_RATELIMITED(fmt, ...) \ | 190 | #define DRM_DEV_ERROR_RATELIMITED(dev, fmt, ...) \ |
182 | ({ \ | 191 | ({ \ |
183 | static DEFINE_RATELIMIT_STATE(_rs, \ | 192 | static DEFINE_RATELIMIT_STATE(_rs, \ |
184 | DEFAULT_RATELIMIT_INTERVAL, \ | 193 | DEFAULT_RATELIMIT_INTERVAL, \ |
185 | DEFAULT_RATELIMIT_BURST); \ | 194 | DEFAULT_RATELIMIT_BURST); \ |
186 | \ | 195 | \ |
187 | if (__ratelimit(&_rs)) \ | 196 | if (__ratelimit(&_rs)) \ |
188 | drm_err(fmt, ##__VA_ARGS__); \ | 197 | DRM_DEV_ERROR(dev, fmt, ##__VA_ARGS__); \ |
189 | }) | 198 | }) |
199 | #define DRM_ERROR_RATELIMITED(fmt, ...) \ | ||
200 | DRM_DEV_ERROR_RATELIMITED(NULL, fmt, ##__VA_ARGS__) | ||
190 | 201 | ||
191 | #define DRM_INFO(fmt, ...) \ | 202 | #define DRM_DEV_INFO(dev, fmt, ...) \ |
192 | printk(KERN_INFO "[" DRM_NAME "] " fmt, ##__VA_ARGS__) | 203 | drm_dev_printk(dev, KERN_INFO, DRM_UT_NONE, __func__, "", fmt, \ |
204 | ##__VA_ARGS__) | ||
205 | #define DRM_INFO(fmt, ...) \ | ||
206 | drm_printk(KERN_INFO, DRM_UT_NONE, __func__, "", fmt, ##__VA_ARGS__) | ||
193 | 207 | ||
194 | #define DRM_INFO_ONCE(fmt, ...) \ | 208 | #define DRM_DEV_INFO_ONCE(dev, fmt, ...) \ |
195 | printk_once(KERN_INFO "[" DRM_NAME "] " fmt, ##__VA_ARGS__) | 209 | ({ \ |
210 | static bool __print_once __read_mostly; \ | ||
211 | if (!__print_once) { \ | ||
212 | __print_once = true; \ | ||
213 | DRM_DEV_INFO(dev, fmt, ##__VA_ARGS__); \ | ||
214 | } \ | ||
215 | }) | ||
216 | #define DRM_INFO_ONCE(fmt, ...) DRM_DEV_INFO_ONCE(NULL, fmt, ##__VA_ARGS__) | ||
196 | 217 | ||
197 | /** | 218 | /** |
198 | * Debug output. | 219 | * Debug output. |
@@ -200,52 +221,51 @@ void drm_err(const char *format, ...); | |||
200 | * \param fmt printf() like format string. | 221 | * \param fmt printf() like format string. |
201 | * \param arg arguments | 222 | * \param arg arguments |
202 | */ | 223 | */ |
224 | #define DRM_DEV_DEBUG(dev, fmt, args...) \ | ||
225 | drm_dev_printk(dev, KERN_DEBUG, DRM_UT_CORE, __func__, "", fmt, \ | ||
226 | ##args) | ||
203 | #define DRM_DEBUG(fmt, args...) \ | 227 | #define DRM_DEBUG(fmt, args...) \ |
204 | do { \ | 228 | drm_printk(KERN_DEBUG, DRM_UT_CORE, __func__, "", fmt, ##args) |
205 | if (unlikely(drm_debug & DRM_UT_CORE)) \ | ||
206 | drm_ut_debug_printk(__func__, fmt, ##args); \ | ||
207 | } while (0) | ||
208 | 229 | ||
230 | #define DRM_DEV_DEBUG_DRIVER(dev, fmt, args...) \ | ||
231 | drm_dev_printk(dev, KERN_DEBUG, DRM_UT_DRIVER, __func__, "", \ | ||
232 | fmt, ##args) | ||
209 | #define DRM_DEBUG_DRIVER(fmt, args...) \ | 233 | #define DRM_DEBUG_DRIVER(fmt, args...) \ |
210 | do { \ | 234 | drm_printk(KERN_DEBUG, DRM_UT_DRIVER, __func__, "", fmt, ##args) |
211 | if (unlikely(drm_debug & DRM_UT_DRIVER)) \ | 235 | |
212 | drm_ut_debug_printk(__func__, fmt, ##args); \ | 236 | #define DRM_DEV_DEBUG_KMS(dev, fmt, args...) \ |
213 | } while (0) | 237 | drm_dev_printk(dev, KERN_DEBUG, DRM_UT_KMS, __func__, "", fmt, \ |
238 | ##args) | ||
214 | #define DRM_DEBUG_KMS(fmt, args...) \ | 239 | #define DRM_DEBUG_KMS(fmt, args...) \ |
215 | do { \ | 240 | drm_printk(KERN_DEBUG, DRM_UT_KMS, __func__, "", fmt, ##args) |
216 | if (unlikely(drm_debug & DRM_UT_KMS)) \ | 241 | |
217 | drm_ut_debug_printk(__func__, fmt, ##args); \ | 242 | #define DRM_DEV_DEBUG_PRIME(dev, fmt, args...) \ |
218 | } while (0) | 243 | drm_dev_printk(dev, KERN_DEBUG, DRM_UT_PRIME, __func__, "", \ |
244 | fmt, ##args) | ||
219 | #define DRM_DEBUG_PRIME(fmt, args...) \ | 245 | #define DRM_DEBUG_PRIME(fmt, args...) \ |
220 | do { \ | 246 | drm_printk(KERN_DEBUG, DRM_UT_PRIME, __func__, "", fmt, ##args) |
221 | if (unlikely(drm_debug & DRM_UT_PRIME)) \ | 247 | |
222 | drm_ut_debug_printk(__func__, fmt, ##args); \ | 248 | #define DRM_DEV_DEBUG_ATOMIC(dev, fmt, args...) \ |
223 | } while (0) | 249 | drm_dev_printk(dev, KERN_DEBUG, DRM_UT_ATOMIC, __func__, "", \ |
250 | fmt, ##args) | ||
224 | #define DRM_DEBUG_ATOMIC(fmt, args...) \ | 251 | #define DRM_DEBUG_ATOMIC(fmt, args...) \ |
225 | do { \ | 252 | drm_printk(KERN_DEBUG, DRM_UT_ATOMIC, __func__, "", fmt, ##args) |
226 | if (unlikely(drm_debug & DRM_UT_ATOMIC)) \ | 253 | |
227 | drm_ut_debug_printk(__func__, fmt, ##args); \ | 254 | #define DRM_DEV_DEBUG_VBL(dev, fmt, args...) \ |
228 | } while (0) | 255 | drm_dev_printk(dev, KERN_DEBUG, DRM_UT_VBL, __func__, "", fmt, \ |
256 | ##args) | ||
229 | #define DRM_DEBUG_VBL(fmt, args...) \ | 257 | #define DRM_DEBUG_VBL(fmt, args...) \ |
230 | do { \ | 258 | drm_printk(KERN_DEBUG, DRM_UT_VBL, __func__, "", fmt, ##args) |
231 | if (unlikely(drm_debug & DRM_UT_VBL)) \ | 259 | |
232 | drm_ut_debug_printk(__func__, fmt, ##args); \ | 260 | #define _DRM_DEV_DEFINE_DEBUG_RATELIMITED(dev, level, fmt, args...) \ |
233 | } while (0) | 261 | ({ \ |
234 | 262 | static DEFINE_RATELIMIT_STATE(_rs, \ | |
235 | #define _DRM_DEFINE_DEBUG_RATELIMITED(level, fmt, args...) \ | 263 | DEFAULT_RATELIMIT_INTERVAL, \ |
236 | do { \ | 264 | DEFAULT_RATELIMIT_BURST); \ |
237 | if (unlikely(drm_debug & DRM_UT_ ## level)) { \ | 265 | if (__ratelimit(&_rs)) \ |
238 | static DEFINE_RATELIMIT_STATE( \ | 266 | drm_dev_printk(dev, KERN_DEBUG, DRM_UT_ ## level, \ |
239 | _rs, \ | 267 | __func__, "", fmt, ##args); \ |
240 | DEFAULT_RATELIMIT_INTERVAL, \ | 268 | }) |
241 | DEFAULT_RATELIMIT_BURST); \ | ||
242 | \ | ||
243 | if (__ratelimit(&_rs)) { \ | ||
244 | drm_ut_debug_printk(__func__, fmt, \ | ||
245 | ##args); \ | ||
246 | } \ | ||
247 | } \ | ||
248 | } while (0) | ||
249 | 269 | ||
250 | /** | 270 | /** |
251 | * Rate limited debug output. Like DRM_DEBUG() but won't flood the log. | 271 | * Rate limited debug output. Like DRM_DEBUG() but won't flood the log. |
@@ -253,14 +273,22 @@ void drm_err(const char *format, ...); | |||
253 | * \param fmt printf() like format string. | 273 | * \param fmt printf() like format string. |
254 | * \param arg arguments | 274 | * \param arg arguments |
255 | */ | 275 | */ |
276 | #define DRM_DEV_DEBUG_RATELIMITED(dev, fmt, args...) \ | ||
277 | DEV__DRM_DEFINE_DEBUG_RATELIMITED(dev, CORE, fmt, ##args) | ||
256 | #define DRM_DEBUG_RATELIMITED(fmt, args...) \ | 278 | #define DRM_DEBUG_RATELIMITED(fmt, args...) \ |
257 | _DRM_DEFINE_DEBUG_RATELIMITED(CORE, fmt, ##args) | 279 | DRM_DEV_DEBUG_RATELIMITED(NULL, fmt, ##args) |
280 | #define DRM_DEV_DEBUG_DRIVER_RATELIMITED(dev, fmt, args...) \ | ||
281 | _DRM_DEV_DEFINE_DEBUG_RATELIMITED(dev, DRIVER, fmt, ##args) | ||
258 | #define DRM_DEBUG_DRIVER_RATELIMITED(fmt, args...) \ | 282 | #define DRM_DEBUG_DRIVER_RATELIMITED(fmt, args...) \ |
259 | _DRM_DEFINE_DEBUG_RATELIMITED(DRIVER, fmt, ##args) | 283 | DRM_DEV_DEBUG_DRIVER_RATELIMITED(NULL, fmt, ##args) |
284 | #define DRM_DEV_DEBUG_KMS_RATELIMITED(dev, fmt, args...) \ | ||
285 | _DRM_DEV_DEFINE_DEBUG_RATELIMITED(dev, KMS, fmt, ##args) | ||
260 | #define DRM_DEBUG_KMS_RATELIMITED(fmt, args...) \ | 286 | #define DRM_DEBUG_KMS_RATELIMITED(fmt, args...) \ |
261 | _DRM_DEFINE_DEBUG_RATELIMITED(KMS, fmt, ##args) | 287 | DRM_DEV_DEBUG_KMS_RATELIMITED(NULL, fmt, ##args) |
288 | #define DRM_DEV_DEBUG_PRIME_RATELIMITED(dev, fmt, args...) \ | ||
289 | _DRM_DEV_DEFINE_DEBUG_RATELIMITED(dev, PRIME, fmt, ##args) | ||
262 | #define DRM_DEBUG_PRIME_RATELIMITED(fmt, args...) \ | 290 | #define DRM_DEBUG_PRIME_RATELIMITED(fmt, args...) \ |
263 | _DRM_DEFINE_DEBUG_RATELIMITED(PRIME, fmt, ##args) | 291 | DRM_DEV_DEBUG_PRIME_RATELIMITED(NULL, fmt, ##args) |
264 | 292 | ||
265 | /*@}*/ | 293 | /*@}*/ |
266 | 294 | ||
diff --git a/include/drm/drm_atomic_helper.h b/include/drm/drm_atomic_helper.h index d86ae5dcd7b4..5a02e499f32b 100644 --- a/include/drm/drm_atomic_helper.h +++ b/include/drm/drm_atomic_helper.h | |||
@@ -29,6 +29,8 @@ | |||
29 | #define DRM_ATOMIC_HELPER_H_ | 29 | #define DRM_ATOMIC_HELPER_H_ |
30 | 30 | ||
31 | #include <drm/drm_crtc.h> | 31 | #include <drm/drm_crtc.h> |
32 | #include <drm/drm_modeset_helper_vtables.h> | ||
33 | #include <drm/drm_modeset_helper.h> | ||
32 | 34 | ||
33 | struct drm_atomic_state; | 35 | struct drm_atomic_state; |
34 | 36 | ||
diff --git a/include/drm/drm_connector.h b/include/drm/drm_connector.h new file mode 100644 index 000000000000..f1576db6c044 --- /dev/null +++ b/include/drm/drm_connector.h | |||
@@ -0,0 +1,747 @@ | |||
1 | /* | ||
2 | * Copyright (c) 2016 Intel Corporation | ||
3 | * | ||
4 | * Permission to use, copy, modify, distribute, and sell this software and its | ||
5 | * documentation for any purpose is hereby granted without fee, provided that | ||
6 | * the above copyright notice appear in all copies and that both that copyright | ||
7 | * notice and this permission notice appear in supporting documentation, and | ||
8 | * that the name of the copyright holders not be used in advertising or | ||
9 | * publicity pertaining to distribution of the software without specific, | ||
10 | * written prior permission. The copyright holders make no representations | ||
11 | * about the suitability of this software for any purpose. It is provided "as | ||
12 | * is" without express or implied warranty. | ||
13 | * | ||
14 | * THE COPYRIGHT HOLDERS DISCLAIM ALL WARRANTIES WITH REGARD TO THIS SOFTWARE, | ||
15 | * INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS, IN NO | ||
16 | * EVENT SHALL THE COPYRIGHT HOLDERS BE LIABLE FOR ANY SPECIAL, INDIRECT OR | ||
17 | * CONSEQUENTIAL DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM LOSS OF USE, | ||
18 | * DATA OR PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER | ||
19 | * TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR PERFORMANCE | ||
20 | * OF THIS SOFTWARE. | ||
21 | */ | ||
22 | |||
23 | #ifndef __DRM_CONNECTOR_H__ | ||
24 | #define __DRM_CONNECTOR_H__ | ||
25 | |||
26 | #include <linux/list.h> | ||
27 | #include <linux/ctype.h> | ||
28 | #include <drm/drm_modeset.h> | ||
29 | |||
30 | struct drm_connector_helper_funcs; | ||
31 | struct drm_device; | ||
32 | struct drm_crtc; | ||
33 | struct drm_encoder; | ||
34 | struct drm_property; | ||
35 | struct drm_property_blob; | ||
36 | struct edid; | ||
37 | |||
38 | enum drm_connector_force { | ||
39 | DRM_FORCE_UNSPECIFIED, | ||
40 | DRM_FORCE_OFF, | ||
41 | DRM_FORCE_ON, /* force on analog part normally */ | ||
42 | DRM_FORCE_ON_DIGITAL, /* for DVI-I use digital connector */ | ||
43 | }; | ||
44 | |||
45 | /** | ||
46 | * enum drm_connector_status - status for a &drm_connector | ||
47 | * | ||
48 | * This enum is used to track the connector status. There are no separate | ||
49 | * #defines for the uapi! | ||
50 | */ | ||
51 | enum drm_connector_status { | ||
52 | /** | ||
53 | * @connector_status_connected: The connector is definitely connected to | ||
54 | * a sink device, and can be enabled. | ||
55 | */ | ||
56 | connector_status_connected = 1, | ||
57 | /** | ||
58 | * @connector_status_disconnected: The connector isn't connected to a | ||
59 | * sink device which can be autodetect. For digital outputs like DP or | ||
60 | * HDMI (which can be realiable probed) this means there's really | ||
61 | * nothing there. It is driver-dependent whether a connector with this | ||
62 | * status can be lit up or not. | ||
63 | */ | ||
64 | connector_status_disconnected = 2, | ||
65 | /** | ||
66 | * @connector_status_unknown: The connector's status could not be | ||
67 | * reliably detected. This happens when probing would either cause | ||
68 | * flicker (like load-detection when the connector is in use), or when a | ||
69 | * hardware resource isn't available (like when load-detection needs a | ||
70 | * free CRTC). It should be possible to light up the connector with one | ||
71 | * of the listed fallback modes. For default configuration userspace | ||
72 | * should only try to light up connectors with unknown status when | ||
73 | * there's not connector with @connector_status_connected. | ||
74 | */ | ||
75 | connector_status_unknown = 3, | ||
76 | }; | ||
77 | |||
78 | enum subpixel_order { | ||
79 | SubPixelUnknown = 0, | ||
80 | SubPixelHorizontalRGB, | ||
81 | SubPixelHorizontalBGR, | ||
82 | SubPixelVerticalRGB, | ||
83 | SubPixelVerticalBGR, | ||
84 | SubPixelNone, | ||
85 | }; | ||
86 | |||
87 | /** | ||
88 | * struct drm_display_info - runtime data about the connected sink | ||
89 | * | ||
90 | * Describes a given display (e.g. CRT or flat panel) and its limitations. For | ||
91 | * fixed display sinks like built-in panels there's not much difference between | ||
92 | * this and struct &drm_connector. But for sinks with a real cable this | ||
93 | * structure is meant to describe all the things at the other end of the cable. | ||
94 | * | ||
95 | * For sinks which provide an EDID this can be filled out by calling | ||
96 | * drm_add_edid_modes(). | ||
97 | */ | ||
98 | struct drm_display_info { | ||
99 | /** | ||
100 | * @name: Name of the display. | ||
101 | */ | ||
102 | char name[DRM_DISPLAY_INFO_LEN]; | ||
103 | |||
104 | /** | ||
105 | * @width_mm: Physical width in mm. | ||
106 | */ | ||
107 | unsigned int width_mm; | ||
108 | /** | ||
109 | * @height_mm: Physical height in mm. | ||
110 | */ | ||
111 | unsigned int height_mm; | ||
112 | |||
113 | /** | ||
114 | * @pixel_clock: Maximum pixel clock supported by the sink, in units of | ||
115 | * 100Hz. This mismatches the clok in &drm_display_mode (which is in | ||
116 | * kHZ), because that's what the EDID uses as base unit. | ||
117 | */ | ||
118 | unsigned int pixel_clock; | ||
119 | /** | ||
120 | * @bpc: Maximum bits per color channel. Used by HDMI and DP outputs. | ||
121 | */ | ||
122 | unsigned int bpc; | ||
123 | |||
124 | /** | ||
125 | * @subpixel_order: Subpixel order of LCD panels. | ||
126 | */ | ||
127 | enum subpixel_order subpixel_order; | ||
128 | |||
129 | #define DRM_COLOR_FORMAT_RGB444 (1<<0) | ||
130 | #define DRM_COLOR_FORMAT_YCRCB444 (1<<1) | ||
131 | #define DRM_COLOR_FORMAT_YCRCB422 (1<<2) | ||
132 | |||
133 | /** | ||
134 | * @color_formats: HDMI Color formats, selects between RGB and YCrCb | ||
135 | * modes. Used DRM_COLOR_FORMAT\_ defines, which are _not_ the same ones | ||
136 | * as used to describe the pixel format in framebuffers, and also don't | ||
137 | * match the formats in @bus_formats which are shared with v4l. | ||
138 | */ | ||
139 | u32 color_formats; | ||
140 | |||
141 | /** | ||
142 | * @bus_formats: Pixel data format on the wire, somewhat redundant with | ||
143 | * @color_formats. Array of size @num_bus_formats encoded using | ||
144 | * MEDIA_BUS_FMT\_ defines shared with v4l and media drivers. | ||
145 | */ | ||
146 | const u32 *bus_formats; | ||
147 | /** | ||
148 | * @num_bus_formats: Size of @bus_formats array. | ||
149 | */ | ||
150 | unsigned int num_bus_formats; | ||
151 | |||
152 | #define DRM_BUS_FLAG_DE_LOW (1<<0) | ||
153 | #define DRM_BUS_FLAG_DE_HIGH (1<<1) | ||
154 | /* drive data on pos. edge */ | ||
155 | #define DRM_BUS_FLAG_PIXDATA_POSEDGE (1<<2) | ||
156 | /* drive data on neg. edge */ | ||
157 | #define DRM_BUS_FLAG_PIXDATA_NEGEDGE (1<<3) | ||
158 | |||
159 | /** | ||
160 | * @bus_flags: Additional information (like pixel signal polarity) for | ||
161 | * the pixel data on the bus, using DRM_BUS_FLAGS\_ defines. | ||
162 | */ | ||
163 | u32 bus_flags; | ||
164 | |||
165 | /** | ||
166 | * @edid_hdmi_dc_modes: Mask of supported hdmi deep color modes. Even | ||
167 | * more stuff redundant with @bus_formats. | ||
168 | */ | ||
169 | u8 edid_hdmi_dc_modes; | ||
170 | |||
171 | /** | ||
172 | * @cea_rev: CEA revision of the HDMI sink. | ||
173 | */ | ||
174 | u8 cea_rev; | ||
175 | }; | ||
176 | |||
177 | int drm_display_info_set_bus_formats(struct drm_display_info *info, | ||
178 | const u32 *formats, | ||
179 | unsigned int num_formats); | ||
180 | |||
181 | /** | ||
182 | * struct drm_connector_state - mutable connector state | ||
183 | * @connector: backpointer to the connector | ||
184 | * @crtc: CRTC to connect connector to, NULL if disabled | ||
185 | * @best_encoder: can be used by helpers and drivers to select the encoder | ||
186 | * @state: backpointer to global drm_atomic_state | ||
187 | */ | ||
188 | struct drm_connector_state { | ||
189 | struct drm_connector *connector; | ||
190 | |||
191 | struct drm_crtc *crtc; /* do not write directly, use drm_atomic_set_crtc_for_connector() */ | ||
192 | |||
193 | struct drm_encoder *best_encoder; | ||
194 | |||
195 | struct drm_atomic_state *state; | ||
196 | }; | ||
197 | |||
198 | /** | ||
199 | * struct drm_connector_funcs - control connectors on a given device | ||
200 | * | ||
201 | * Each CRTC may have one or more connectors attached to it. The functions | ||
202 | * below allow the core DRM code to control connectors, enumerate available modes, | ||
203 | * etc. | ||
204 | */ | ||
205 | struct drm_connector_funcs { | ||
206 | /** | ||
207 | * @dpms: | ||
208 | * | ||
209 | * Legacy entry point to set the per-connector DPMS state. Legacy DPMS | ||
210 | * is exposed as a standard property on the connector, but diverted to | ||
211 | * this callback in the drm core. Note that atomic drivers don't | ||
212 | * implement the 4 level DPMS support on the connector any more, but | ||
213 | * instead only have an on/off "ACTIVE" property on the CRTC object. | ||
214 | * | ||
215 | * Drivers implementing atomic modeset should use | ||
216 | * drm_atomic_helper_connector_dpms() to implement this hook. | ||
217 | * | ||
218 | * RETURNS: | ||
219 | * | ||
220 | * 0 on success or a negative error code on failure. | ||
221 | */ | ||
222 | int (*dpms)(struct drm_connector *connector, int mode); | ||
223 | |||
224 | /** | ||
225 | * @reset: | ||
226 | * | ||
227 | * Reset connector hardware and software state to off. This function isn't | ||
228 | * called by the core directly, only through drm_mode_config_reset(). | ||
229 | * It's not a helper hook only for historical reasons. | ||
230 | * | ||
231 | * Atomic drivers can use drm_atomic_helper_connector_reset() to reset | ||
232 | * atomic state using this hook. | ||
233 | */ | ||
234 | void (*reset)(struct drm_connector *connector); | ||
235 | |||
236 | /** | ||
237 | * @detect: | ||
238 | * | ||
239 | * Check to see if anything is attached to the connector. The parameter | ||
240 | * force is set to false whilst polling, true when checking the | ||
241 | * connector due to a user request. force can be used by the driver to | ||
242 | * avoid expensive, destructive operations during automated probing. | ||
243 | * | ||
244 | * FIXME: | ||
245 | * | ||
246 | * Note that this hook is only called by the probe helper. It's not in | ||
247 | * the helper library vtable purely for historical reasons. The only DRM | ||
248 | * core entry point to probe connector state is @fill_modes. | ||
249 | * | ||
250 | * RETURNS: | ||
251 | * | ||
252 | * drm_connector_status indicating the connector's status. | ||
253 | */ | ||
254 | enum drm_connector_status (*detect)(struct drm_connector *connector, | ||
255 | bool force); | ||
256 | |||
257 | /** | ||
258 | * @force: | ||
259 | * | ||
260 | * This function is called to update internal encoder state when the | ||
261 | * connector is forced to a certain state by userspace, either through | ||
262 | * the sysfs interfaces or on the kernel cmdline. In that case the | ||
263 | * @detect callback isn't called. | ||
264 | * | ||
265 | * FIXME: | ||
266 | * | ||
267 | * Note that this hook is only called by the probe helper. It's not in | ||
268 | * the helper library vtable purely for historical reasons. The only DRM | ||
269 | * core entry point to probe connector state is @fill_modes. | ||
270 | */ | ||
271 | void (*force)(struct drm_connector *connector); | ||
272 | |||
273 | /** | ||
274 | * @fill_modes: | ||
275 | * | ||
276 | * Entry point for output detection and basic mode validation. The | ||
277 | * driver should reprobe the output if needed (e.g. when hotplug | ||
278 | * handling is unreliable), add all detected modes to connector->modes | ||
279 | * and filter out any the device can't support in any configuration. It | ||
280 | * also needs to filter out any modes wider or higher than the | ||
281 | * parameters max_width and max_height indicate. | ||
282 | * | ||
283 | * The drivers must also prune any modes no longer valid from | ||
284 | * connector->modes. Furthermore it must update connector->status and | ||
285 | * connector->edid. If no EDID has been received for this output | ||
286 | * connector->edid must be NULL. | ||
287 | * | ||
288 | * Drivers using the probe helpers should use | ||
289 | * drm_helper_probe_single_connector_modes() or | ||
290 | * drm_helper_probe_single_connector_modes_nomerge() to implement this | ||
291 | * function. | ||
292 | * | ||
293 | * RETURNS: | ||
294 | * | ||
295 | * The number of modes detected and filled into connector->modes. | ||
296 | */ | ||
297 | int (*fill_modes)(struct drm_connector *connector, uint32_t max_width, uint32_t max_height); | ||
298 | |||
299 | /** | ||
300 | * @set_property: | ||
301 | * | ||
302 | * This is the legacy entry point to update a property attached to the | ||
303 | * connector. | ||
304 | * | ||
305 | * Drivers implementing atomic modeset should use | ||
306 | * drm_atomic_helper_connector_set_property() to implement this hook. | ||
307 | * | ||
308 | * This callback is optional if the driver does not support any legacy | ||
309 | * driver-private properties. | ||
310 | * | ||
311 | * RETURNS: | ||
312 | * | ||
313 | * 0 on success or a negative error code on failure. | ||
314 | */ | ||
315 | int (*set_property)(struct drm_connector *connector, struct drm_property *property, | ||
316 | uint64_t val); | ||
317 | |||
318 | /** | ||
319 | * @late_register: | ||
320 | * | ||
321 | * This optional hook can be used to register additional userspace | ||
322 | * interfaces attached to the connector, light backlight control, i2c, | ||
323 | * DP aux or similar interfaces. It is called late in the driver load | ||
324 | * sequence from drm_connector_register() when registering all the | ||
325 | * core drm connector interfaces. Everything added from this callback | ||
326 | * should be unregistered in the early_unregister callback. | ||
327 | * | ||
328 | * Returns: | ||
329 | * | ||
330 | * 0 on success, or a negative error code on failure. | ||
331 | */ | ||
332 | int (*late_register)(struct drm_connector *connector); | ||
333 | |||
334 | /** | ||
335 | * @early_unregister: | ||
336 | * | ||
337 | * This optional hook should be used to unregister the additional | ||
338 | * userspace interfaces attached to the connector from | ||
339 | * late_unregister(). It is called from drm_connector_unregister(), | ||
340 | * early in the driver unload sequence to disable userspace access | ||
341 | * before data structures are torndown. | ||
342 | */ | ||
343 | void (*early_unregister)(struct drm_connector *connector); | ||
344 | |||
345 | /** | ||
346 | * @destroy: | ||
347 | * | ||
348 | * Clean up connector resources. This is called at driver unload time | ||
349 | * through drm_mode_config_cleanup(). It can also be called at runtime | ||
350 | * when a connector is being hot-unplugged for drivers that support | ||
351 | * connector hotplugging (e.g. DisplayPort MST). | ||
352 | */ | ||
353 | void (*destroy)(struct drm_connector *connector); | ||
354 | |||
355 | /** | ||
356 | * @atomic_duplicate_state: | ||
357 | * | ||
358 | * Duplicate the current atomic state for this connector and return it. | ||
359 | * The core and helpers gurantee that any atomic state duplicated with | ||
360 | * this hook and still owned by the caller (i.e. not transferred to the | ||
361 | * driver by calling ->atomic_commit() from struct | ||
362 | * &drm_mode_config_funcs) will be cleaned up by calling the | ||
363 | * @atomic_destroy_state hook in this structure. | ||
364 | * | ||
365 | * Atomic drivers which don't subclass struct &drm_connector_state should use | ||
366 | * drm_atomic_helper_connector_duplicate_state(). Drivers that subclass the | ||
367 | * state structure to extend it with driver-private state should use | ||
368 | * __drm_atomic_helper_connector_duplicate_state() to make sure shared state is | ||
369 | * duplicated in a consistent fashion across drivers. | ||
370 | * | ||
371 | * It is an error to call this hook before connector->state has been | ||
372 | * initialized correctly. | ||
373 | * | ||
374 | * NOTE: | ||
375 | * | ||
376 | * If the duplicate state references refcounted resources this hook must | ||
377 | * acquire a reference for each of them. The driver must release these | ||
378 | * references again in @atomic_destroy_state. | ||
379 | * | ||
380 | * RETURNS: | ||
381 | * | ||
382 | * Duplicated atomic state or NULL when the allocation failed. | ||
383 | */ | ||
384 | struct drm_connector_state *(*atomic_duplicate_state)(struct drm_connector *connector); | ||
385 | |||
386 | /** | ||
387 | * @atomic_destroy_state: | ||
388 | * | ||
389 | * Destroy a state duplicated with @atomic_duplicate_state and release | ||
390 | * or unreference all resources it references | ||
391 | */ | ||
392 | void (*atomic_destroy_state)(struct drm_connector *connector, | ||
393 | struct drm_connector_state *state); | ||
394 | |||
395 | /** | ||
396 | * @atomic_set_property: | ||
397 | * | ||
398 | * Decode a driver-private property value and store the decoded value | ||
399 | * into the passed-in state structure. Since the atomic core decodes all | ||
400 | * standardized properties (even for extensions beyond the core set of | ||
401 | * properties which might not be implemented by all drivers) this | ||
402 | * requires drivers to subclass the state structure. | ||
403 | * | ||
404 | * Such driver-private properties should really only be implemented for | ||
405 | * truly hardware/vendor specific state. Instead it is preferred to | ||
406 | * standardize atomic extension and decode the properties used to expose | ||
407 | * such an extension in the core. | ||
408 | * | ||
409 | * Do not call this function directly, use | ||
410 | * drm_atomic_connector_set_property() instead. | ||
411 | * | ||
412 | * This callback is optional if the driver does not support any | ||
413 | * driver-private atomic properties. | ||
414 | * | ||
415 | * NOTE: | ||
416 | * | ||
417 | * This function is called in the state assembly phase of atomic | ||
418 | * modesets, which can be aborted for any reason (including on | ||
419 | * userspace's request to just check whether a configuration would be | ||
420 | * possible). Drivers MUST NOT touch any persistent state (hardware or | ||
421 | * software) or data structures except the passed in @state parameter. | ||
422 | * | ||
423 | * Also since userspace controls in which order properties are set this | ||
424 | * function must not do any input validation (since the state update is | ||
425 | * incomplete and hence likely inconsistent). Instead any such input | ||
426 | * validation must be done in the various atomic_check callbacks. | ||
427 | * | ||
428 | * RETURNS: | ||
429 | * | ||
430 | * 0 if the property has been found, -EINVAL if the property isn't | ||
431 | * implemented by the driver (which shouldn't ever happen, the core only | ||
432 | * asks for properties attached to this connector). No other validation | ||
433 | * is allowed by the driver. The core already checks that the property | ||
434 | * value is within the range (integer, valid enum value, ...) the driver | ||
435 | * set when registering the property. | ||
436 | */ | ||
437 | int (*atomic_set_property)(struct drm_connector *connector, | ||
438 | struct drm_connector_state *state, | ||
439 | struct drm_property *property, | ||
440 | uint64_t val); | ||
441 | |||
442 | /** | ||
443 | * @atomic_get_property: | ||
444 | * | ||
445 | * Reads out the decoded driver-private property. This is used to | ||
446 | * implement the GETCONNECTOR IOCTL. | ||
447 | * | ||
448 | * Do not call this function directly, use | ||
449 | * drm_atomic_connector_get_property() instead. | ||
450 | * | ||
451 | * This callback is optional if the driver does not support any | ||
452 | * driver-private atomic properties. | ||
453 | * | ||
454 | * RETURNS: | ||
455 | * | ||
456 | * 0 on success, -EINVAL if the property isn't implemented by the | ||
457 | * driver (which shouldn't ever happen, the core only asks for | ||
458 | * properties attached to this connector). | ||
459 | */ | ||
460 | int (*atomic_get_property)(struct drm_connector *connector, | ||
461 | const struct drm_connector_state *state, | ||
462 | struct drm_property *property, | ||
463 | uint64_t *val); | ||
464 | }; | ||
465 | |||
466 | /* mode specified on the command line */ | ||
467 | struct drm_cmdline_mode { | ||
468 | bool specified; | ||
469 | bool refresh_specified; | ||
470 | bool bpp_specified; | ||
471 | int xres, yres; | ||
472 | int bpp; | ||
473 | int refresh; | ||
474 | bool rb; | ||
475 | bool interlace; | ||
476 | bool cvt; | ||
477 | bool margins; | ||
478 | enum drm_connector_force force; | ||
479 | }; | ||
480 | |||
481 | /** | ||
482 | * struct drm_connector - central DRM connector control structure | ||
483 | * @dev: parent DRM device | ||
484 | * @kdev: kernel device for sysfs attributes | ||
485 | * @attr: sysfs attributes | ||
486 | * @head: list management | ||
487 | * @base: base KMS object | ||
488 | * @name: human readable name, can be overwritten by the driver | ||
489 | * @connector_type: one of the DRM_MODE_CONNECTOR_<foo> types from drm_mode.h | ||
490 | * @connector_type_id: index into connector type enum | ||
491 | * @interlace_allowed: can this connector handle interlaced modes? | ||
492 | * @doublescan_allowed: can this connector handle doublescan? | ||
493 | * @stereo_allowed: can this connector handle stereo modes? | ||
494 | * @registered: is this connector exposed (registered) with userspace? | ||
495 | * @modes: modes available on this connector (from fill_modes() + user) | ||
496 | * @status: one of the drm_connector_status enums (connected, not, or unknown) | ||
497 | * @probed_modes: list of modes derived directly from the display | ||
498 | * @funcs: connector control functions | ||
499 | * @edid_blob_ptr: DRM property containing EDID if present | ||
500 | * @properties: property tracking for this connector | ||
501 | * @dpms: current dpms state | ||
502 | * @helper_private: mid-layer private data | ||
503 | * @cmdline_mode: mode line parsed from the kernel cmdline for this connector | ||
504 | * @force: a DRM_FORCE_<foo> state for forced mode sets | ||
505 | * @override_edid: has the EDID been overwritten through debugfs for testing? | ||
506 | * @encoder_ids: valid encoders for this connector | ||
507 | * @encoder: encoder driving this connector, if any | ||
508 | * @eld: EDID-like data, if present | ||
509 | * @dvi_dual: dual link DVI, if found | ||
510 | * @max_tmds_clock: max clock rate, if found | ||
511 | * @latency_present: AV delay info from ELD, if found | ||
512 | * @video_latency: video latency info from ELD, if found | ||
513 | * @audio_latency: audio latency info from ELD, if found | ||
514 | * @null_edid_counter: track sinks that give us all zeros for the EDID | ||
515 | * @bad_edid_counter: track sinks that give us an EDID with invalid checksum | ||
516 | * @edid_corrupt: indicates whether the last read EDID was corrupt | ||
517 | * @debugfs_entry: debugfs directory for this connector | ||
518 | * @state: current atomic state for this connector | ||
519 | * @has_tile: is this connector connected to a tiled monitor | ||
520 | * @tile_group: tile group for the connected monitor | ||
521 | * @tile_is_single_monitor: whether the tile is one monitor housing | ||
522 | * @num_h_tile: number of horizontal tiles in the tile group | ||
523 | * @num_v_tile: number of vertical tiles in the tile group | ||
524 | * @tile_h_loc: horizontal location of this tile | ||
525 | * @tile_v_loc: vertical location of this tile | ||
526 | * @tile_h_size: horizontal size of this tile. | ||
527 | * @tile_v_size: vertical size of this tile. | ||
528 | * | ||
529 | * Each connector may be connected to one or more CRTCs, or may be clonable by | ||
530 | * another connector if they can share a CRTC. Each connector also has a specific | ||
531 | * position in the broader display (referred to as a 'screen' though it could | ||
532 | * span multiple monitors). | ||
533 | */ | ||
534 | struct drm_connector { | ||
535 | struct drm_device *dev; | ||
536 | struct device *kdev; | ||
537 | struct device_attribute *attr; | ||
538 | struct list_head head; | ||
539 | |||
540 | struct drm_mode_object base; | ||
541 | |||
542 | char *name; | ||
543 | |||
544 | /** | ||
545 | * @index: Compacted connector index, which matches the position inside | ||
546 | * the mode_config.list for drivers not supporting hot-add/removing. Can | ||
547 | * be used as an array index. It is invariant over the lifetime of the | ||
548 | * connector. | ||
549 | */ | ||
550 | unsigned index; | ||
551 | |||
552 | int connector_type; | ||
553 | int connector_type_id; | ||
554 | bool interlace_allowed; | ||
555 | bool doublescan_allowed; | ||
556 | bool stereo_allowed; | ||
557 | bool registered; | ||
558 | struct list_head modes; /* list of modes on this connector */ | ||
559 | |||
560 | enum drm_connector_status status; | ||
561 | |||
562 | /* these are modes added by probing with DDC or the BIOS */ | ||
563 | struct list_head probed_modes; | ||
564 | |||
565 | /** | ||
566 | * @display_info: Display information is filled from EDID information | ||
567 | * when a display is detected. For non hot-pluggable displays such as | ||
568 | * flat panels in embedded systems, the driver should initialize the | ||
569 | * display_info.width_mm and display_info.height_mm fields with the | ||
570 | * physical size of the display. | ||
571 | */ | ||
572 | struct drm_display_info display_info; | ||
573 | const struct drm_connector_funcs *funcs; | ||
574 | |||
575 | struct drm_property_blob *edid_blob_ptr; | ||
576 | struct drm_object_properties properties; | ||
577 | |||
578 | /** | ||
579 | * @path_blob_ptr: | ||
580 | * | ||
581 | * DRM blob property data for the DP MST path property. | ||
582 | */ | ||
583 | struct drm_property_blob *path_blob_ptr; | ||
584 | |||
585 | /** | ||
586 | * @tile_blob_ptr: | ||
587 | * | ||
588 | * DRM blob property data for the tile property (used mostly by DP MST). | ||
589 | * This is meant for screens which are driven through separate display | ||
590 | * pipelines represented by &drm_crtc, which might not be running with | ||
591 | * genlocked clocks. For tiled panels which are genlocked, like | ||
592 | * dual-link LVDS or dual-link DSI, the driver should try to not expose | ||
593 | * the tiling and virtualize both &drm_crtc and &drm_plane if needed. | ||
594 | */ | ||
595 | struct drm_property_blob *tile_blob_ptr; | ||
596 | |||
597 | /* should we poll this connector for connects and disconnects */ | ||
598 | /* hot plug detectable */ | ||
599 | #define DRM_CONNECTOR_POLL_HPD (1 << 0) | ||
600 | /* poll for connections */ | ||
601 | #define DRM_CONNECTOR_POLL_CONNECT (1 << 1) | ||
602 | /* can cleanly poll for disconnections without flickering the screen */ | ||
603 | /* DACs should rarely do this without a lot of testing */ | ||
604 | #define DRM_CONNECTOR_POLL_DISCONNECT (1 << 2) | ||
605 | |||
606 | /** | ||
607 | * @polled: | ||
608 | * | ||
609 | * Connector polling mode, a combination of | ||
610 | * | ||
611 | * DRM_CONNECTOR_POLL_HPD | ||
612 | * The connector generates hotplug events and doesn't need to be | ||
613 | * periodically polled. The CONNECT and DISCONNECT flags must not | ||
614 | * be set together with the HPD flag. | ||
615 | * | ||
616 | * DRM_CONNECTOR_POLL_CONNECT | ||
617 | * Periodically poll the connector for connection. | ||
618 | * | ||
619 | * DRM_CONNECTOR_POLL_DISCONNECT | ||
620 | * Periodically poll the connector for disconnection. | ||
621 | * | ||
622 | * Set to 0 for connectors that don't support connection status | ||
623 | * discovery. | ||
624 | */ | ||
625 | uint8_t polled; | ||
626 | |||
627 | /* requested DPMS state */ | ||
628 | int dpms; | ||
629 | |||
630 | const struct drm_connector_helper_funcs *helper_private; | ||
631 | |||
632 | /* forced on connector */ | ||
633 | struct drm_cmdline_mode cmdline_mode; | ||
634 | enum drm_connector_force force; | ||
635 | bool override_edid; | ||
636 | |||
637 | #define DRM_CONNECTOR_MAX_ENCODER 3 | ||
638 | uint32_t encoder_ids[DRM_CONNECTOR_MAX_ENCODER]; | ||
639 | struct drm_encoder *encoder; /* currently active encoder */ | ||
640 | |||
641 | #define MAX_ELD_BYTES 128 | ||
642 | /* EDID bits */ | ||
643 | uint8_t eld[MAX_ELD_BYTES]; | ||
644 | bool dvi_dual; | ||
645 | int max_tmds_clock; /* in MHz */ | ||
646 | bool latency_present[2]; | ||
647 | int video_latency[2]; /* [0]: progressive, [1]: interlaced */ | ||
648 | int audio_latency[2]; | ||
649 | int null_edid_counter; /* needed to workaround some HW bugs where we get all 0s */ | ||
650 | unsigned bad_edid_counter; | ||
651 | |||
652 | /* Flag for raw EDID header corruption - used in Displayport | ||
653 | * compliance testing - * Displayport Link CTS Core 1.2 rev1.1 4.2.2.6 | ||
654 | */ | ||
655 | bool edid_corrupt; | ||
656 | |||
657 | struct dentry *debugfs_entry; | ||
658 | |||
659 | struct drm_connector_state *state; | ||
660 | |||
661 | /* DisplayID bits */ | ||
662 | bool has_tile; | ||
663 | struct drm_tile_group *tile_group; | ||
664 | bool tile_is_single_monitor; | ||
665 | |||
666 | uint8_t num_h_tile, num_v_tile; | ||
667 | uint8_t tile_h_loc, tile_v_loc; | ||
668 | uint16_t tile_h_size, tile_v_size; | ||
669 | }; | ||
670 | |||
671 | #define obj_to_connector(x) container_of(x, struct drm_connector, base) | ||
672 | |||
673 | int drm_connector_init(struct drm_device *dev, | ||
674 | struct drm_connector *connector, | ||
675 | const struct drm_connector_funcs *funcs, | ||
676 | int connector_type); | ||
677 | int drm_connector_register(struct drm_connector *connector); | ||
678 | void drm_connector_unregister(struct drm_connector *connector); | ||
679 | int drm_mode_connector_attach_encoder(struct drm_connector *connector, | ||
680 | struct drm_encoder *encoder); | ||
681 | |||
682 | void drm_connector_cleanup(struct drm_connector *connector); | ||
683 | static inline unsigned drm_connector_index(struct drm_connector *connector) | ||
684 | { | ||
685 | return connector->index; | ||
686 | } | ||
687 | |||
688 | /** | ||
689 | * drm_connector_lookup - lookup connector object | ||
690 | * @dev: DRM device | ||
691 | * @id: connector object id | ||
692 | * | ||
693 | * This function looks up the connector object specified by id | ||
694 | * add takes a reference to it. | ||
695 | */ | ||
696 | static inline struct drm_connector *drm_connector_lookup(struct drm_device *dev, | ||
697 | uint32_t id) | ||
698 | { | ||
699 | struct drm_mode_object *mo; | ||
700 | mo = drm_mode_object_find(dev, id, DRM_MODE_OBJECT_CONNECTOR); | ||
701 | return mo ? obj_to_connector(mo) : NULL; | ||
702 | } | ||
703 | |||
704 | /** | ||
705 | * drm_connector_reference - incr the connector refcnt | ||
706 | * @connector: connector | ||
707 | * | ||
708 | * This function increments the connector's refcount. | ||
709 | */ | ||
710 | static inline void drm_connector_reference(struct drm_connector *connector) | ||
711 | { | ||
712 | drm_mode_object_reference(&connector->base); | ||
713 | } | ||
714 | |||
715 | /** | ||
716 | * drm_connector_unreference - unref a connector | ||
717 | * @connector: connector to unref | ||
718 | * | ||
719 | * This function decrements the connector's refcount and frees it if it drops to zero. | ||
720 | */ | ||
721 | static inline void drm_connector_unreference(struct drm_connector *connector) | ||
722 | { | ||
723 | drm_mode_object_unreference(&connector->base); | ||
724 | } | ||
725 | |||
726 | const char *drm_get_connector_status_name(enum drm_connector_status status); | ||
727 | const char *drm_get_subpixel_order_name(enum subpixel_order order); | ||
728 | const char *drm_get_dpms_name(int val); | ||
729 | const char *drm_get_dvi_i_subconnector_name(int val); | ||
730 | const char *drm_get_dvi_i_select_name(int val); | ||
731 | const char *drm_get_tv_subconnector_name(int val); | ||
732 | const char *drm_get_tv_select_name(int val); | ||
733 | |||
734 | int drm_mode_create_dvi_i_properties(struct drm_device *dev); | ||
735 | int drm_mode_create_tv_properties(struct drm_device *dev, | ||
736 | unsigned int num_modes, | ||
737 | const char * const modes[]); | ||
738 | int drm_mode_create_scaling_mode_property(struct drm_device *dev); | ||
739 | int drm_mode_create_aspect_ratio_property(struct drm_device *dev); | ||
740 | int drm_mode_create_suggested_offset_properties(struct drm_device *dev); | ||
741 | |||
742 | int drm_mode_connector_set_path_property(struct drm_connector *connector, | ||
743 | const char *path); | ||
744 | int drm_mode_connector_set_tile_property(struct drm_connector *connector); | ||
745 | int drm_mode_connector_update_edid_property(struct drm_connector *connector, | ||
746 | const struct edid *edid); | ||
747 | #endif | ||
diff --git a/include/drm/drm_crtc.h b/include/drm/drm_crtc.h index b618b506b04d..3fa0275e509f 100644 --- a/include/drm/drm_crtc.h +++ b/include/drm/drm_crtc.h | |||
@@ -36,40 +36,19 @@ | |||
36 | #include <uapi/drm/drm_fourcc.h> | 36 | #include <uapi/drm/drm_fourcc.h> |
37 | #include <drm/drm_modeset_lock.h> | 37 | #include <drm/drm_modeset_lock.h> |
38 | #include <drm/drm_rect.h> | 38 | #include <drm/drm_rect.h> |
39 | #include <drm/drm_modeset.h> | ||
40 | #include <drm/drm_framebuffer.h> | ||
41 | #include <drm/drm_modes.h> | ||
42 | #include <drm/drm_connector.h> | ||
39 | 43 | ||
40 | struct drm_device; | 44 | struct drm_device; |
41 | struct drm_mode_set; | 45 | struct drm_mode_set; |
42 | struct drm_framebuffer; | ||
43 | struct drm_object_properties; | ||
44 | struct drm_file; | 46 | struct drm_file; |
45 | struct drm_clip_rect; | 47 | struct drm_clip_rect; |
46 | struct device_node; | 48 | struct device_node; |
47 | struct fence; | 49 | struct fence; |
48 | struct edid; | 50 | struct edid; |
49 | 51 | ||
50 | struct drm_mode_object { | ||
51 | uint32_t id; | ||
52 | uint32_t type; | ||
53 | struct drm_object_properties *properties; | ||
54 | struct kref refcount; | ||
55 | void (*free_cb)(struct kref *kref); | ||
56 | }; | ||
57 | |||
58 | #define DRM_OBJECT_MAX_PROPERTY 24 | ||
59 | struct drm_object_properties { | ||
60 | int count, atomic_count; | ||
61 | /* NOTE: if we ever start dynamically destroying properties (ie. | ||
62 | * not at drm_mode_config_cleanup() time), then we'd have to do | ||
63 | * a better job of detaching property from mode objects to avoid | ||
64 | * dangling property pointers: | ||
65 | */ | ||
66 | struct drm_property *properties[DRM_OBJECT_MAX_PROPERTY]; | ||
67 | /* do not read/write values directly, but use drm_object_property_get_value() | ||
68 | * and drm_object_property_set_value(): | ||
69 | */ | ||
70 | uint64_t values[DRM_OBJECT_MAX_PROPERTY]; | ||
71 | }; | ||
72 | |||
73 | static inline int64_t U642I64(uint64_t val) | 52 | static inline int64_t U642I64(uint64_t val) |
74 | { | 53 | { |
75 | return (int64_t)*((int64_t *)&val); | 54 | return (int64_t)*((int64_t *)&val); |
@@ -94,70 +73,6 @@ static inline uint64_t I642U64(int64_t val) | |||
94 | #define DRM_REFLECT_Y BIT(5) | 73 | #define DRM_REFLECT_Y BIT(5) |
95 | #define DRM_REFLECT_MASK (DRM_REFLECT_X | DRM_REFLECT_Y) | 74 | #define DRM_REFLECT_MASK (DRM_REFLECT_X | DRM_REFLECT_Y) |
96 | 75 | ||
97 | enum drm_connector_force { | ||
98 | DRM_FORCE_UNSPECIFIED, | ||
99 | DRM_FORCE_OFF, | ||
100 | DRM_FORCE_ON, /* force on analog part normally */ | ||
101 | DRM_FORCE_ON_DIGITAL, /* for DVI-I use digital connector */ | ||
102 | }; | ||
103 | |||
104 | #include <drm/drm_modes.h> | ||
105 | |||
106 | enum drm_connector_status { | ||
107 | connector_status_connected = 1, | ||
108 | connector_status_disconnected = 2, | ||
109 | connector_status_unknown = 3, | ||
110 | }; | ||
111 | |||
112 | enum subpixel_order { | ||
113 | SubPixelUnknown = 0, | ||
114 | SubPixelHorizontalRGB, | ||
115 | SubPixelHorizontalBGR, | ||
116 | SubPixelVerticalRGB, | ||
117 | SubPixelVerticalBGR, | ||
118 | SubPixelNone, | ||
119 | }; | ||
120 | |||
121 | #define DRM_COLOR_FORMAT_RGB444 (1<<0) | ||
122 | #define DRM_COLOR_FORMAT_YCRCB444 (1<<1) | ||
123 | #define DRM_COLOR_FORMAT_YCRCB422 (1<<2) | ||
124 | |||
125 | #define DRM_BUS_FLAG_DE_LOW (1<<0) | ||
126 | #define DRM_BUS_FLAG_DE_HIGH (1<<1) | ||
127 | /* drive data on pos. edge */ | ||
128 | #define DRM_BUS_FLAG_PIXDATA_POSEDGE (1<<2) | ||
129 | /* drive data on neg. edge */ | ||
130 | #define DRM_BUS_FLAG_PIXDATA_NEGEDGE (1<<3) | ||
131 | |||
132 | /* | ||
133 | * Describes a given display (e.g. CRT or flat panel) and its limitations. | ||
134 | */ | ||
135 | struct drm_display_info { | ||
136 | char name[DRM_DISPLAY_INFO_LEN]; | ||
137 | |||
138 | /* Physical size */ | ||
139 | unsigned int width_mm; | ||
140 | unsigned int height_mm; | ||
141 | |||
142 | /* Clock limits FIXME: storage format */ | ||
143 | unsigned int min_vfreq, max_vfreq; | ||
144 | unsigned int min_hfreq, max_hfreq; | ||
145 | unsigned int pixel_clock; | ||
146 | unsigned int bpc; | ||
147 | |||
148 | enum subpixel_order subpixel_order; | ||
149 | u32 color_formats; | ||
150 | |||
151 | const u32 *bus_formats; | ||
152 | unsigned int num_bus_formats; | ||
153 | u32 bus_flags; | ||
154 | |||
155 | /* Mask of supported hdmi deep color modes */ | ||
156 | u8 edid_hdmi_dc_modes; | ||
157 | |||
158 | u8 cea_rev; | ||
159 | }; | ||
160 | |||
161 | /* data corresponds to displayid vend/prod/serial */ | 76 | /* data corresponds to displayid vend/prod/serial */ |
162 | struct drm_tile_group { | 77 | struct drm_tile_group { |
163 | struct kref refcount; | 78 | struct kref refcount; |
@@ -166,101 +81,6 @@ struct drm_tile_group { | |||
166 | u8 group_data[8]; | 81 | u8 group_data[8]; |
167 | }; | 82 | }; |
168 | 83 | ||
169 | /** | ||
170 | * struct drm_framebuffer_funcs - framebuffer hooks | ||
171 | */ | ||
172 | struct drm_framebuffer_funcs { | ||
173 | /** | ||
174 | * @destroy: | ||
175 | * | ||
176 | * Clean up framebuffer resources, specifically also unreference the | ||
177 | * backing storage. The core guarantees to call this function for every | ||
178 | * framebuffer successfully created by ->fb_create() in | ||
179 | * &drm_mode_config_funcs. Drivers must also call | ||
180 | * drm_framebuffer_cleanup() to release DRM core resources for this | ||
181 | * framebuffer. | ||
182 | */ | ||
183 | void (*destroy)(struct drm_framebuffer *framebuffer); | ||
184 | |||
185 | /** | ||
186 | * @create_handle: | ||
187 | * | ||
188 | * Create a buffer handle in the driver-specific buffer manager (either | ||
189 | * GEM or TTM) valid for the passed-in struct &drm_file. This is used by | ||
190 | * the core to implement the GETFB IOCTL, which returns (for | ||
191 | * sufficiently priviledged user) also a native buffer handle. This can | ||
192 | * be used for seamless transitions between modesetting clients by | ||
193 | * copying the current screen contents to a private buffer and blending | ||
194 | * between that and the new contents. | ||
195 | * | ||
196 | * GEM based drivers should call drm_gem_handle_create() to create the | ||
197 | * handle. | ||
198 | * | ||
199 | * RETURNS: | ||
200 | * | ||
201 | * 0 on success or a negative error code on failure. | ||
202 | */ | ||
203 | int (*create_handle)(struct drm_framebuffer *fb, | ||
204 | struct drm_file *file_priv, | ||
205 | unsigned int *handle); | ||
206 | /** | ||
207 | * @dirty: | ||
208 | * | ||
209 | * Optional callback for the dirty fb IOCTL. | ||
210 | * | ||
211 | * Userspace can notify the driver via this callback that an area of the | ||
212 | * framebuffer has changed and should be flushed to the display | ||
213 | * hardware. This can also be used internally, e.g. by the fbdev | ||
214 | * emulation, though that's not the case currently. | ||
215 | * | ||
216 | * See documentation in drm_mode.h for the struct drm_mode_fb_dirty_cmd | ||
217 | * for more information as all the semantics and arguments have a one to | ||
218 | * one mapping on this function. | ||
219 | * | ||
220 | * RETURNS: | ||
221 | * | ||
222 | * 0 on success or a negative error code on failure. | ||
223 | */ | ||
224 | int (*dirty)(struct drm_framebuffer *framebuffer, | ||
225 | struct drm_file *file_priv, unsigned flags, | ||
226 | unsigned color, struct drm_clip_rect *clips, | ||
227 | unsigned num_clips); | ||
228 | }; | ||
229 | |||
230 | struct drm_framebuffer { | ||
231 | struct drm_device *dev; | ||
232 | /* | ||
233 | * Note that the fb is refcounted for the benefit of driver internals, | ||
234 | * for example some hw, disabling a CRTC/plane is asynchronous, and | ||
235 | * scanout does not actually complete until the next vblank. So some | ||
236 | * cleanup (like releasing the reference(s) on the backing GEM bo(s)) | ||
237 | * should be deferred. In cases like this, the driver would like to | ||
238 | * hold a ref to the fb even though it has already been removed from | ||
239 | * userspace perspective. | ||
240 | * The refcount is stored inside the mode object. | ||
241 | */ | ||
242 | /* | ||
243 | * Place on the dev->mode_config.fb_list, access protected by | ||
244 | * dev->mode_config.fb_lock. | ||
245 | */ | ||
246 | struct list_head head; | ||
247 | struct drm_mode_object base; | ||
248 | const struct drm_framebuffer_funcs *funcs; | ||
249 | unsigned int pitches[4]; | ||
250 | unsigned int offsets[4]; | ||
251 | uint64_t modifier[4]; | ||
252 | unsigned int width; | ||
253 | unsigned int height; | ||
254 | /* depth can be 15 or 16 */ | ||
255 | unsigned int depth; | ||
256 | int bits_per_pixel; | ||
257 | int flags; | ||
258 | uint32_t pixel_format; /* fourcc format */ | ||
259 | int hot_x; | ||
260 | int hot_y; | ||
261 | struct list_head filp_head; | ||
262 | }; | ||
263 | |||
264 | struct drm_property_blob { | 84 | struct drm_property_blob { |
265 | struct drm_mode_object base; | 85 | struct drm_mode_object base; |
266 | struct drm_device *dev; | 86 | struct drm_device *dev; |
@@ -289,7 +109,6 @@ struct drm_property { | |||
289 | }; | 109 | }; |
290 | 110 | ||
291 | struct drm_crtc; | 111 | struct drm_crtc; |
292 | struct drm_connector; | ||
293 | struct drm_encoder; | 112 | struct drm_encoder; |
294 | struct drm_pending_vblank_event; | 113 | struct drm_pending_vblank_event; |
295 | struct drm_plane; | 114 | struct drm_plane; |
@@ -298,7 +117,6 @@ struct drm_atomic_state; | |||
298 | 117 | ||
299 | struct drm_crtc_helper_funcs; | 118 | struct drm_crtc_helper_funcs; |
300 | struct drm_encoder_helper_funcs; | 119 | struct drm_encoder_helper_funcs; |
301 | struct drm_connector_helper_funcs; | ||
302 | struct drm_plane_helper_funcs; | 120 | struct drm_plane_helper_funcs; |
303 | 121 | ||
304 | /** | 122 | /** |
@@ -547,16 +365,6 @@ struct drm_crtc_funcs { | |||
547 | * counter and timestamp tracking though, e.g. if they have accurate | 365 | * counter and timestamp tracking though, e.g. if they have accurate |
548 | * timestamp registers in hardware. | 366 | * timestamp registers in hardware. |
549 | * | 367 | * |
550 | * FIXME: | ||
551 | * | ||
552 | * Up to that point drivers need to manage events themselves and can use | ||
553 | * even->base.list freely for that. Specifically they need to ensure | ||
554 | * that they don't send out page flip (or vblank) events for which the | ||
555 | * corresponding drm file has been closed already. The drm core | ||
556 | * unfortunately does not (yet) take care of that. Therefore drivers | ||
557 | * currently must clean up and release pending events in their | ||
558 | * ->preclose driver function. | ||
559 | * | ||
560 | * This callback is optional. | 368 | * This callback is optional. |
561 | * | 369 | * |
562 | * NOTE: | 370 | * NOTE: |
@@ -854,291 +662,6 @@ struct drm_crtc { | |||
854 | }; | 662 | }; |
855 | 663 | ||
856 | /** | 664 | /** |
857 | * struct drm_connector_state - mutable connector state | ||
858 | * @connector: backpointer to the connector | ||
859 | * @crtc: CRTC to connect connector to, NULL if disabled | ||
860 | * @best_encoder: can be used by helpers and drivers to select the encoder | ||
861 | * @state: backpointer to global drm_atomic_state | ||
862 | */ | ||
863 | struct drm_connector_state { | ||
864 | struct drm_connector *connector; | ||
865 | |||
866 | struct drm_crtc *crtc; /* do not write directly, use drm_atomic_set_crtc_for_connector() */ | ||
867 | |||
868 | struct drm_encoder *best_encoder; | ||
869 | |||
870 | struct drm_atomic_state *state; | ||
871 | }; | ||
872 | |||
873 | /** | ||
874 | * struct drm_connector_funcs - control connectors on a given device | ||
875 | * | ||
876 | * Each CRTC may have one or more connectors attached to it. The functions | ||
877 | * below allow the core DRM code to control connectors, enumerate available modes, | ||
878 | * etc. | ||
879 | */ | ||
880 | struct drm_connector_funcs { | ||
881 | /** | ||
882 | * @dpms: | ||
883 | * | ||
884 | * Legacy entry point to set the per-connector DPMS state. Legacy DPMS | ||
885 | * is exposed as a standard property on the connector, but diverted to | ||
886 | * this callback in the drm core. Note that atomic drivers don't | ||
887 | * implement the 4 level DPMS support on the connector any more, but | ||
888 | * instead only have an on/off "ACTIVE" property on the CRTC object. | ||
889 | * | ||
890 | * Drivers implementing atomic modeset should use | ||
891 | * drm_atomic_helper_connector_dpms() to implement this hook. | ||
892 | * | ||
893 | * RETURNS: | ||
894 | * | ||
895 | * 0 on success or a negative error code on failure. | ||
896 | */ | ||
897 | int (*dpms)(struct drm_connector *connector, int mode); | ||
898 | |||
899 | /** | ||
900 | * @reset: | ||
901 | * | ||
902 | * Reset connector hardware and software state to off. This function isn't | ||
903 | * called by the core directly, only through drm_mode_config_reset(). | ||
904 | * It's not a helper hook only for historical reasons. | ||
905 | * | ||
906 | * Atomic drivers can use drm_atomic_helper_connector_reset() to reset | ||
907 | * atomic state using this hook. | ||
908 | */ | ||
909 | void (*reset)(struct drm_connector *connector); | ||
910 | |||
911 | /** | ||
912 | * @detect: | ||
913 | * | ||
914 | * Check to see if anything is attached to the connector. The parameter | ||
915 | * force is set to false whilst polling, true when checking the | ||
916 | * connector due to a user request. force can be used by the driver to | ||
917 | * avoid expensive, destructive operations during automated probing. | ||
918 | * | ||
919 | * FIXME: | ||
920 | * | ||
921 | * Note that this hook is only called by the probe helper. It's not in | ||
922 | * the helper library vtable purely for historical reasons. The only DRM | ||
923 | * core entry point to probe connector state is @fill_modes. | ||
924 | * | ||
925 | * RETURNS: | ||
926 | * | ||
927 | * drm_connector_status indicating the connector's status. | ||
928 | */ | ||
929 | enum drm_connector_status (*detect)(struct drm_connector *connector, | ||
930 | bool force); | ||
931 | |||
932 | /** | ||
933 | * @force: | ||
934 | * | ||
935 | * This function is called to update internal encoder state when the | ||
936 | * connector is forced to a certain state by userspace, either through | ||
937 | * the sysfs interfaces or on the kernel cmdline. In that case the | ||
938 | * @detect callback isn't called. | ||
939 | * | ||
940 | * FIXME: | ||
941 | * | ||
942 | * Note that this hook is only called by the probe helper. It's not in | ||
943 | * the helper library vtable purely for historical reasons. The only DRM | ||
944 | * core entry point to probe connector state is @fill_modes. | ||
945 | */ | ||
946 | void (*force)(struct drm_connector *connector); | ||
947 | |||
948 | /** | ||
949 | * @fill_modes: | ||
950 | * | ||
951 | * Entry point for output detection and basic mode validation. The | ||
952 | * driver should reprobe the output if needed (e.g. when hotplug | ||
953 | * handling is unreliable), add all detected modes to connector->modes | ||
954 | * and filter out any the device can't support in any configuration. It | ||
955 | * also needs to filter out any modes wider or higher than the | ||
956 | * parameters max_width and max_height indicate. | ||
957 | * | ||
958 | * The drivers must also prune any modes no longer valid from | ||
959 | * connector->modes. Furthermore it must update connector->status and | ||
960 | * connector->edid. If no EDID has been received for this output | ||
961 | * connector->edid must be NULL. | ||
962 | * | ||
963 | * Drivers using the probe helpers should use | ||
964 | * drm_helper_probe_single_connector_modes() or | ||
965 | * drm_helper_probe_single_connector_modes_nomerge() to implement this | ||
966 | * function. | ||
967 | * | ||
968 | * RETURNS: | ||
969 | * | ||
970 | * The number of modes detected and filled into connector->modes. | ||
971 | */ | ||
972 | int (*fill_modes)(struct drm_connector *connector, uint32_t max_width, uint32_t max_height); | ||
973 | |||
974 | /** | ||
975 | * @set_property: | ||
976 | * | ||
977 | * This is the legacy entry point to update a property attached to the | ||
978 | * connector. | ||
979 | * | ||
980 | * Drivers implementing atomic modeset should use | ||
981 | * drm_atomic_helper_connector_set_property() to implement this hook. | ||
982 | * | ||
983 | * This callback is optional if the driver does not support any legacy | ||
984 | * driver-private properties. | ||
985 | * | ||
986 | * RETURNS: | ||
987 | * | ||
988 | * 0 on success or a negative error code on failure. | ||
989 | */ | ||
990 | int (*set_property)(struct drm_connector *connector, struct drm_property *property, | ||
991 | uint64_t val); | ||
992 | |||
993 | /** | ||
994 | * @late_register: | ||
995 | * | ||
996 | * This optional hook can be used to register additional userspace | ||
997 | * interfaces attached to the connector, light backlight control, i2c, | ||
998 | * DP aux or similar interfaces. It is called late in the driver load | ||
999 | * sequence from drm_connector_register() when registering all the | ||
1000 | * core drm connector interfaces. Everything added from this callback | ||
1001 | * should be unregistered in the early_unregister callback. | ||
1002 | * | ||
1003 | * Returns: | ||
1004 | * | ||
1005 | * 0 on success, or a negative error code on failure. | ||
1006 | */ | ||
1007 | int (*late_register)(struct drm_connector *connector); | ||
1008 | |||
1009 | /** | ||
1010 | * @early_unregister: | ||
1011 | * | ||
1012 | * This optional hook should be used to unregister the additional | ||
1013 | * userspace interfaces attached to the connector from | ||
1014 | * late_unregister(). It is called from drm_connector_unregister(), | ||
1015 | * early in the driver unload sequence to disable userspace access | ||
1016 | * before data structures are torndown. | ||
1017 | */ | ||
1018 | void (*early_unregister)(struct drm_connector *connector); | ||
1019 | |||
1020 | /** | ||
1021 | * @destroy: | ||
1022 | * | ||
1023 | * Clean up connector resources. This is called at driver unload time | ||
1024 | * through drm_mode_config_cleanup(). It can also be called at runtime | ||
1025 | * when a connector is being hot-unplugged for drivers that support | ||
1026 | * connector hotplugging (e.g. DisplayPort MST). | ||
1027 | */ | ||
1028 | void (*destroy)(struct drm_connector *connector); | ||
1029 | |||
1030 | /** | ||
1031 | * @atomic_duplicate_state: | ||
1032 | * | ||
1033 | * Duplicate the current atomic state for this connector and return it. | ||
1034 | * The core and helpers gurantee that any atomic state duplicated with | ||
1035 | * this hook and still owned by the caller (i.e. not transferred to the | ||
1036 | * driver by calling ->atomic_commit() from struct | ||
1037 | * &drm_mode_config_funcs) will be cleaned up by calling the | ||
1038 | * @atomic_destroy_state hook in this structure. | ||
1039 | * | ||
1040 | * Atomic drivers which don't subclass struct &drm_connector_state should use | ||
1041 | * drm_atomic_helper_connector_duplicate_state(). Drivers that subclass the | ||
1042 | * state structure to extend it with driver-private state should use | ||
1043 | * __drm_atomic_helper_connector_duplicate_state() to make sure shared state is | ||
1044 | * duplicated in a consistent fashion across drivers. | ||
1045 | * | ||
1046 | * It is an error to call this hook before connector->state has been | ||
1047 | * initialized correctly. | ||
1048 | * | ||
1049 | * NOTE: | ||
1050 | * | ||
1051 | * If the duplicate state references refcounted resources this hook must | ||
1052 | * acquire a reference for each of them. The driver must release these | ||
1053 | * references again in @atomic_destroy_state. | ||
1054 | * | ||
1055 | * RETURNS: | ||
1056 | * | ||
1057 | * Duplicated atomic state or NULL when the allocation failed. | ||
1058 | */ | ||
1059 | struct drm_connector_state *(*atomic_duplicate_state)(struct drm_connector *connector); | ||
1060 | |||
1061 | /** | ||
1062 | * @atomic_destroy_state: | ||
1063 | * | ||
1064 | * Destroy a state duplicated with @atomic_duplicate_state and release | ||
1065 | * or unreference all resources it references | ||
1066 | */ | ||
1067 | void (*atomic_destroy_state)(struct drm_connector *connector, | ||
1068 | struct drm_connector_state *state); | ||
1069 | |||
1070 | /** | ||
1071 | * @atomic_set_property: | ||
1072 | * | ||
1073 | * Decode a driver-private property value and store the decoded value | ||
1074 | * into the passed-in state structure. Since the atomic core decodes all | ||
1075 | * standardized properties (even for extensions beyond the core set of | ||
1076 | * properties which might not be implemented by all drivers) this | ||
1077 | * requires drivers to subclass the state structure. | ||
1078 | * | ||
1079 | * Such driver-private properties should really only be implemented for | ||
1080 | * truly hardware/vendor specific state. Instead it is preferred to | ||
1081 | * standardize atomic extension and decode the properties used to expose | ||
1082 | * such an extension in the core. | ||
1083 | * | ||
1084 | * Do not call this function directly, use | ||
1085 | * drm_atomic_connector_set_property() instead. | ||
1086 | * | ||
1087 | * This callback is optional if the driver does not support any | ||
1088 | * driver-private atomic properties. | ||
1089 | * | ||
1090 | * NOTE: | ||
1091 | * | ||
1092 | * This function is called in the state assembly phase of atomic | ||
1093 | * modesets, which can be aborted for any reason (including on | ||
1094 | * userspace's request to just check whether a configuration would be | ||
1095 | * possible). Drivers MUST NOT touch any persistent state (hardware or | ||
1096 | * software) or data structures except the passed in @state parameter. | ||
1097 | * | ||
1098 | * Also since userspace controls in which order properties are set this | ||
1099 | * function must not do any input validation (since the state update is | ||
1100 | * incomplete and hence likely inconsistent). Instead any such input | ||
1101 | * validation must be done in the various atomic_check callbacks. | ||
1102 | * | ||
1103 | * RETURNS: | ||
1104 | * | ||
1105 | * 0 if the property has been found, -EINVAL if the property isn't | ||
1106 | * implemented by the driver (which shouldn't ever happen, the core only | ||
1107 | * asks for properties attached to this connector). No other validation | ||
1108 | * is allowed by the driver. The core already checks that the property | ||
1109 | * value is within the range (integer, valid enum value, ...) the driver | ||
1110 | * set when registering the property. | ||
1111 | */ | ||
1112 | int (*atomic_set_property)(struct drm_connector *connector, | ||
1113 | struct drm_connector_state *state, | ||
1114 | struct drm_property *property, | ||
1115 | uint64_t val); | ||
1116 | |||
1117 | /** | ||
1118 | * @atomic_get_property: | ||
1119 | * | ||
1120 | * Reads out the decoded driver-private property. This is used to | ||
1121 | * implement the GETCONNECTOR IOCTL. | ||
1122 | * | ||
1123 | * Do not call this function directly, use | ||
1124 | * drm_atomic_connector_get_property() instead. | ||
1125 | * | ||
1126 | * This callback is optional if the driver does not support any | ||
1127 | * driver-private atomic properties. | ||
1128 | * | ||
1129 | * RETURNS: | ||
1130 | * | ||
1131 | * 0 on success, -EINVAL if the property isn't implemented by the | ||
1132 | * driver (which shouldn't ever happen, the core only asks for | ||
1133 | * properties attached to this connector). | ||
1134 | */ | ||
1135 | int (*atomic_get_property)(struct drm_connector *connector, | ||
1136 | const struct drm_connector_state *state, | ||
1137 | struct drm_property *property, | ||
1138 | uint64_t *val); | ||
1139 | }; | ||
1140 | |||
1141 | /** | ||
1142 | * struct drm_encoder_funcs - encoder controls | 665 | * struct drm_encoder_funcs - encoder controls |
1143 | * | 666 | * |
1144 | * Encoders sit between CRTCs and connectors. | 667 | * Encoders sit between CRTCs and connectors. |
@@ -1189,15 +712,13 @@ struct drm_encoder_funcs { | |||
1189 | void (*early_unregister)(struct drm_encoder *encoder); | 712 | void (*early_unregister)(struct drm_encoder *encoder); |
1190 | }; | 713 | }; |
1191 | 714 | ||
1192 | #define DRM_CONNECTOR_MAX_ENCODER 3 | ||
1193 | |||
1194 | /** | 715 | /** |
1195 | * struct drm_encoder - central DRM encoder structure | 716 | * struct drm_encoder - central DRM encoder structure |
1196 | * @dev: parent DRM device | 717 | * @dev: parent DRM device |
1197 | * @head: list management | 718 | * @head: list management |
1198 | * @base: base KMS object | 719 | * @base: base KMS object |
1199 | * @name: human readable name, can be overwritten by the driver | 720 | * @name: human readable name, can be overwritten by the driver |
1200 | * @encoder_type: one of the %DRM_MODE_ENCODER_<foo> types in drm_mode.h | 721 | * @encoder_type: one of the DRM_MODE_ENCODER_<foo> types in drm_mode.h |
1201 | * @possible_crtcs: bitmask of potential CRTC bindings | 722 | * @possible_crtcs: bitmask of potential CRTC bindings |
1202 | * @possible_clones: bitmask of potential sibling encoders for cloning | 723 | * @possible_clones: bitmask of potential sibling encoders for cloning |
1203 | * @crtc: currently bound CRTC | 724 | * @crtc: currently bound CRTC |
@@ -1231,171 +752,6 @@ struct drm_encoder { | |||
1231 | const struct drm_encoder_helper_funcs *helper_private; | 752 | const struct drm_encoder_helper_funcs *helper_private; |
1232 | }; | 753 | }; |
1233 | 754 | ||
1234 | /* should we poll this connector for connects and disconnects */ | ||
1235 | /* hot plug detectable */ | ||
1236 | #define DRM_CONNECTOR_POLL_HPD (1 << 0) | ||
1237 | /* poll for connections */ | ||
1238 | #define DRM_CONNECTOR_POLL_CONNECT (1 << 1) | ||
1239 | /* can cleanly poll for disconnections without flickering the screen */ | ||
1240 | /* DACs should rarely do this without a lot of testing */ | ||
1241 | #define DRM_CONNECTOR_POLL_DISCONNECT (1 << 2) | ||
1242 | |||
1243 | #define MAX_ELD_BYTES 128 | ||
1244 | |||
1245 | /** | ||
1246 | * struct drm_connector - central DRM connector control structure | ||
1247 | * @dev: parent DRM device | ||
1248 | * @kdev: kernel device for sysfs attributes | ||
1249 | * @attr: sysfs attributes | ||
1250 | * @head: list management | ||
1251 | * @base: base KMS object | ||
1252 | * @name: human readable name, can be overwritten by the driver | ||
1253 | * @connector_type: one of the %DRM_MODE_CONNECTOR_<foo> types from drm_mode.h | ||
1254 | * @connector_type_id: index into connector type enum | ||
1255 | * @interlace_allowed: can this connector handle interlaced modes? | ||
1256 | * @doublescan_allowed: can this connector handle doublescan? | ||
1257 | * @stereo_allowed: can this connector handle stereo modes? | ||
1258 | * @registered: is this connector exposed (registered) with userspace? | ||
1259 | * @modes: modes available on this connector (from fill_modes() + user) | ||
1260 | * @status: one of the drm_connector_status enums (connected, not, or unknown) | ||
1261 | * @probed_modes: list of modes derived directly from the display | ||
1262 | * @display_info: information about attached display (e.g. from EDID) | ||
1263 | * @funcs: connector control functions | ||
1264 | * @edid_blob_ptr: DRM property containing EDID if present | ||
1265 | * @properties: property tracking for this connector | ||
1266 | * @polled: a %DRM_CONNECTOR_POLL_<foo> value for core driven polling | ||
1267 | * @dpms: current dpms state | ||
1268 | * @helper_private: mid-layer private data | ||
1269 | * @cmdline_mode: mode line parsed from the kernel cmdline for this connector | ||
1270 | * @force: a %DRM_FORCE_<foo> state for forced mode sets | ||
1271 | * @override_edid: has the EDID been overwritten through debugfs for testing? | ||
1272 | * @encoder_ids: valid encoders for this connector | ||
1273 | * @encoder: encoder driving this connector, if any | ||
1274 | * @eld: EDID-like data, if present | ||
1275 | * @dvi_dual: dual link DVI, if found | ||
1276 | * @max_tmds_clock: max clock rate, if found | ||
1277 | * @latency_present: AV delay info from ELD, if found | ||
1278 | * @video_latency: video latency info from ELD, if found | ||
1279 | * @audio_latency: audio latency info from ELD, if found | ||
1280 | * @null_edid_counter: track sinks that give us all zeros for the EDID | ||
1281 | * @bad_edid_counter: track sinks that give us an EDID with invalid checksum | ||
1282 | * @edid_corrupt: indicates whether the last read EDID was corrupt | ||
1283 | * @debugfs_entry: debugfs directory for this connector | ||
1284 | * @state: current atomic state for this connector | ||
1285 | * @has_tile: is this connector connected to a tiled monitor | ||
1286 | * @tile_group: tile group for the connected monitor | ||
1287 | * @tile_is_single_monitor: whether the tile is one monitor housing | ||
1288 | * @num_h_tile: number of horizontal tiles in the tile group | ||
1289 | * @num_v_tile: number of vertical tiles in the tile group | ||
1290 | * @tile_h_loc: horizontal location of this tile | ||
1291 | * @tile_v_loc: vertical location of this tile | ||
1292 | * @tile_h_size: horizontal size of this tile. | ||
1293 | * @tile_v_size: vertical size of this tile. | ||
1294 | * | ||
1295 | * Each connector may be connected to one or more CRTCs, or may be clonable by | ||
1296 | * another connector if they can share a CRTC. Each connector also has a specific | ||
1297 | * position in the broader display (referred to as a 'screen' though it could | ||
1298 | * span multiple monitors). | ||
1299 | */ | ||
1300 | struct drm_connector { | ||
1301 | struct drm_device *dev; | ||
1302 | struct device *kdev; | ||
1303 | struct device_attribute *attr; | ||
1304 | struct list_head head; | ||
1305 | |||
1306 | struct drm_mode_object base; | ||
1307 | |||
1308 | char *name; | ||
1309 | |||
1310 | /** | ||
1311 | * @index: Compacted connector index, which matches the position inside | ||
1312 | * the mode_config.list for drivers not supporting hot-add/removing. Can | ||
1313 | * be used as an array index. It is invariant over the lifetime of the | ||
1314 | * connector. | ||
1315 | */ | ||
1316 | unsigned index; | ||
1317 | |||
1318 | int connector_type; | ||
1319 | int connector_type_id; | ||
1320 | bool interlace_allowed; | ||
1321 | bool doublescan_allowed; | ||
1322 | bool stereo_allowed; | ||
1323 | bool registered; | ||
1324 | struct list_head modes; /* list of modes on this connector */ | ||
1325 | |||
1326 | enum drm_connector_status status; | ||
1327 | |||
1328 | /* these are modes added by probing with DDC or the BIOS */ | ||
1329 | struct list_head probed_modes; | ||
1330 | |||
1331 | struct drm_display_info display_info; | ||
1332 | const struct drm_connector_funcs *funcs; | ||
1333 | |||
1334 | struct drm_property_blob *edid_blob_ptr; | ||
1335 | struct drm_object_properties properties; | ||
1336 | |||
1337 | /** | ||
1338 | * @path_blob_ptr: | ||
1339 | * | ||
1340 | * DRM blob property data for the DP MST path property. | ||
1341 | */ | ||
1342 | struct drm_property_blob *path_blob_ptr; | ||
1343 | |||
1344 | /** | ||
1345 | * @tile_blob_ptr: | ||
1346 | * | ||
1347 | * DRM blob property data for the tile property (used mostly by DP MST). | ||
1348 | * This is meant for screens which are driven through separate display | ||
1349 | * pipelines represented by &drm_crtc, which might not be running with | ||
1350 | * genlocked clocks. For tiled panels which are genlocked, like | ||
1351 | * dual-link LVDS or dual-link DSI, the driver should try to not expose | ||
1352 | * the tiling and virtualize both &drm_crtc and &drm_plane if needed. | ||
1353 | */ | ||
1354 | struct drm_property_blob *tile_blob_ptr; | ||
1355 | |||
1356 | uint8_t polled; /* DRM_CONNECTOR_POLL_* */ | ||
1357 | |||
1358 | /* requested DPMS state */ | ||
1359 | int dpms; | ||
1360 | |||
1361 | const struct drm_connector_helper_funcs *helper_private; | ||
1362 | |||
1363 | /* forced on connector */ | ||
1364 | struct drm_cmdline_mode cmdline_mode; | ||
1365 | enum drm_connector_force force; | ||
1366 | bool override_edid; | ||
1367 | uint32_t encoder_ids[DRM_CONNECTOR_MAX_ENCODER]; | ||
1368 | struct drm_encoder *encoder; /* currently active encoder */ | ||
1369 | |||
1370 | /* EDID bits */ | ||
1371 | uint8_t eld[MAX_ELD_BYTES]; | ||
1372 | bool dvi_dual; | ||
1373 | int max_tmds_clock; /* in MHz */ | ||
1374 | bool latency_present[2]; | ||
1375 | int video_latency[2]; /* [0]: progressive, [1]: interlaced */ | ||
1376 | int audio_latency[2]; | ||
1377 | int null_edid_counter; /* needed to workaround some HW bugs where we get all 0s */ | ||
1378 | unsigned bad_edid_counter; | ||
1379 | |||
1380 | /* Flag for raw EDID header corruption - used in Displayport | ||
1381 | * compliance testing - * Displayport Link CTS Core 1.2 rev1.1 4.2.2.6 | ||
1382 | */ | ||
1383 | bool edid_corrupt; | ||
1384 | |||
1385 | struct dentry *debugfs_entry; | ||
1386 | |||
1387 | struct drm_connector_state *state; | ||
1388 | |||
1389 | /* DisplayID bits */ | ||
1390 | bool has_tile; | ||
1391 | struct drm_tile_group *tile_group; | ||
1392 | bool tile_is_single_monitor; | ||
1393 | |||
1394 | uint8_t num_h_tile, num_v_tile; | ||
1395 | uint8_t tile_h_loc, tile_v_loc; | ||
1396 | uint16_t tile_h_size, tile_v_size; | ||
1397 | }; | ||
1398 | |||
1399 | /** | 755 | /** |
1400 | * struct drm_plane_state - mutable plane state | 756 | * struct drm_plane_state - mutable plane state |
1401 | * @plane: backpointer to the plane | 757 | * @plane: backpointer to the plane |
@@ -2650,12 +2006,6 @@ struct drm_mode_config { | |||
2650 | */ | 2006 | */ |
2651 | struct drm_property *aspect_ratio_property; | 2007 | struct drm_property *aspect_ratio_property; |
2652 | /** | 2008 | /** |
2653 | * @dirty_info_property: Optional connector property to give userspace a | ||
2654 | * hint that the DIRTY_FB ioctl should be used. | ||
2655 | */ | ||
2656 | struct drm_property *dirty_info_property; | ||
2657 | |||
2658 | /** | ||
2659 | * @degamma_lut_property: Optional CRTC property to set the LUT used to | 2009 | * @degamma_lut_property: Optional CRTC property to set the LUT used to |
2660 | * convert the framebuffer's colors to linear gamma. | 2010 | * convert the framebuffer's colors to linear gamma. |
2661 | */ | 2011 | */ |
@@ -2741,7 +2091,6 @@ struct drm_mode_config { | |||
2741 | for_each_if ((encoder_mask) & (1 << drm_encoder_index(encoder))) | 2091 | for_each_if ((encoder_mask) & (1 << drm_encoder_index(encoder))) |
2742 | 2092 | ||
2743 | #define obj_to_crtc(x) container_of(x, struct drm_crtc, base) | 2093 | #define obj_to_crtc(x) container_of(x, struct drm_crtc, base) |
2744 | #define obj_to_connector(x) container_of(x, struct drm_connector, base) | ||
2745 | #define obj_to_encoder(x) container_of(x, struct drm_encoder, base) | 2094 | #define obj_to_encoder(x) container_of(x, struct drm_encoder, base) |
2746 | #define obj_to_mode(x) container_of(x, struct drm_display_mode, base) | 2095 | #define obj_to_mode(x) container_of(x, struct drm_display_mode, base) |
2747 | #define obj_to_fb(x) container_of(x, struct drm_framebuffer, base) | 2096 | #define obj_to_fb(x) container_of(x, struct drm_framebuffer, base) |
@@ -2787,19 +2136,6 @@ static inline uint32_t drm_crtc_mask(struct drm_crtc *crtc) | |||
2787 | return 1 << drm_crtc_index(crtc); | 2136 | return 1 << drm_crtc_index(crtc); |
2788 | } | 2137 | } |
2789 | 2138 | ||
2790 | int drm_connector_init(struct drm_device *dev, | ||
2791 | struct drm_connector *connector, | ||
2792 | const struct drm_connector_funcs *funcs, | ||
2793 | int connector_type); | ||
2794 | int drm_connector_register(struct drm_connector *connector); | ||
2795 | void drm_connector_unregister(struct drm_connector *connector); | ||
2796 | |||
2797 | extern void drm_connector_cleanup(struct drm_connector *connector); | ||
2798 | static inline unsigned drm_connector_index(struct drm_connector *connector) | ||
2799 | { | ||
2800 | return connector->index; | ||
2801 | } | ||
2802 | |||
2803 | extern __printf(5, 6) | 2139 | extern __printf(5, 6) |
2804 | int drm_encoder_init(struct drm_device *dev, | 2140 | int drm_encoder_init(struct drm_device *dev, |
2805 | struct drm_encoder *encoder, | 2141 | struct drm_encoder *encoder, |
@@ -2868,27 +2204,10 @@ extern int drm_crtc_force_disable_all(struct drm_device *dev); | |||
2868 | 2204 | ||
2869 | extern void drm_encoder_cleanup(struct drm_encoder *encoder); | 2205 | extern void drm_encoder_cleanup(struct drm_encoder *encoder); |
2870 | 2206 | ||
2871 | extern const char *drm_get_connector_status_name(enum drm_connector_status status); | ||
2872 | extern const char *drm_get_subpixel_order_name(enum subpixel_order order); | ||
2873 | extern const char *drm_get_dpms_name(int val); | ||
2874 | extern const char *drm_get_dvi_i_subconnector_name(int val); | ||
2875 | extern const char *drm_get_dvi_i_select_name(int val); | ||
2876 | extern const char *drm_get_tv_subconnector_name(int val); | ||
2877 | extern const char *drm_get_tv_select_name(int val); | ||
2878 | extern void drm_mode_config_init(struct drm_device *dev); | 2207 | extern void drm_mode_config_init(struct drm_device *dev); |
2879 | extern void drm_mode_config_reset(struct drm_device *dev); | 2208 | extern void drm_mode_config_reset(struct drm_device *dev); |
2880 | extern void drm_mode_config_cleanup(struct drm_device *dev); | 2209 | extern void drm_mode_config_cleanup(struct drm_device *dev); |
2881 | 2210 | ||
2882 | extern int drm_mode_connector_set_path_property(struct drm_connector *connector, | ||
2883 | const char *path); | ||
2884 | int drm_mode_connector_set_tile_property(struct drm_connector *connector); | ||
2885 | extern int drm_mode_connector_update_edid_property(struct drm_connector *connector, | ||
2886 | const struct edid *edid); | ||
2887 | |||
2888 | extern int drm_display_info_set_bus_formats(struct drm_display_info *info, | ||
2889 | const u32 *formats, | ||
2890 | unsigned int num_formats); | ||
2891 | |||
2892 | static inline bool drm_property_type_is(struct drm_property *property, | 2211 | static inline bool drm_property_type_is(struct drm_property *property, |
2893 | uint32_t type) | 2212 | uint32_t type) |
2894 | { | 2213 | { |
@@ -2904,14 +2223,6 @@ extern int drm_object_property_set_value(struct drm_mode_object *obj, | |||
2904 | extern int drm_object_property_get_value(struct drm_mode_object *obj, | 2223 | extern int drm_object_property_get_value(struct drm_mode_object *obj, |
2905 | struct drm_property *property, | 2224 | struct drm_property *property, |
2906 | uint64_t *value); | 2225 | uint64_t *value); |
2907 | extern int drm_framebuffer_init(struct drm_device *dev, | ||
2908 | struct drm_framebuffer *fb, | ||
2909 | const struct drm_framebuffer_funcs *funcs); | ||
2910 | extern struct drm_framebuffer *drm_framebuffer_lookup(struct drm_device *dev, | ||
2911 | uint32_t id); | ||
2912 | extern void drm_framebuffer_remove(struct drm_framebuffer *fb); | ||
2913 | extern void drm_framebuffer_cleanup(struct drm_framebuffer *fb); | ||
2914 | extern void drm_framebuffer_unregister_private(struct drm_framebuffer *fb); | ||
2915 | 2226 | ||
2916 | extern void drm_object_attach_property(struct drm_mode_object *obj, | 2227 | extern void drm_object_attach_property(struct drm_mode_object *obj, |
2917 | struct drm_property *property, | 2228 | struct drm_property *property, |
@@ -2942,22 +2253,17 @@ struct drm_property_blob *drm_property_create_blob(struct drm_device *dev, | |||
2942 | const void *data); | 2253 | const void *data); |
2943 | struct drm_property_blob *drm_property_lookup_blob(struct drm_device *dev, | 2254 | struct drm_property_blob *drm_property_lookup_blob(struct drm_device *dev, |
2944 | uint32_t id); | 2255 | uint32_t id); |
2256 | int drm_property_replace_global_blob(struct drm_device *dev, | ||
2257 | struct drm_property_blob **replace, | ||
2258 | size_t length, | ||
2259 | const void *data, | ||
2260 | struct drm_mode_object *obj_holds_id, | ||
2261 | struct drm_property *prop_holds_id); | ||
2945 | struct drm_property_blob *drm_property_reference_blob(struct drm_property_blob *blob); | 2262 | struct drm_property_blob *drm_property_reference_blob(struct drm_property_blob *blob); |
2946 | void drm_property_unreference_blob(struct drm_property_blob *blob); | 2263 | void drm_property_unreference_blob(struct drm_property_blob *blob); |
2947 | extern void drm_property_destroy(struct drm_device *dev, struct drm_property *property); | 2264 | extern void drm_property_destroy(struct drm_device *dev, struct drm_property *property); |
2948 | extern int drm_property_add_enum(struct drm_property *property, int index, | 2265 | extern int drm_property_add_enum(struct drm_property *property, int index, |
2949 | uint64_t value, const char *name); | 2266 | uint64_t value, const char *name); |
2950 | extern int drm_mode_create_dvi_i_properties(struct drm_device *dev); | ||
2951 | extern int drm_mode_create_tv_properties(struct drm_device *dev, | ||
2952 | unsigned int num_modes, | ||
2953 | const char * const modes[]); | ||
2954 | extern int drm_mode_create_scaling_mode_property(struct drm_device *dev); | ||
2955 | extern int drm_mode_create_aspect_ratio_property(struct drm_device *dev); | ||
2956 | extern int drm_mode_create_dirty_info_property(struct drm_device *dev); | ||
2957 | extern int drm_mode_create_suggested_offset_properties(struct drm_device *dev); | ||
2958 | |||
2959 | extern int drm_mode_connector_attach_encoder(struct drm_connector *connector, | ||
2960 | struct drm_encoder *encoder); | ||
2961 | extern int drm_mode_crtc_set_gamma_size(struct drm_crtc *crtc, | 2267 | extern int drm_mode_crtc_set_gamma_size(struct drm_crtc *crtc, |
2962 | int gamma_size); | 2268 | int gamma_size); |
2963 | 2269 | ||
@@ -2993,11 +2299,6 @@ int drm_plane_create_zpos_immutable_property(struct drm_plane *plane, | |||
2993 | unsigned int zpos); | 2299 | unsigned int zpos); |
2994 | 2300 | ||
2995 | /* Helpers */ | 2301 | /* Helpers */ |
2996 | struct drm_mode_object *drm_mode_object_find(struct drm_device *dev, | ||
2997 | uint32_t id, uint32_t type); | ||
2998 | void drm_mode_object_reference(struct drm_mode_object *obj); | ||
2999 | void drm_mode_object_unreference(struct drm_mode_object *obj); | ||
3000 | |||
3001 | static inline struct drm_plane *drm_plane_find(struct drm_device *dev, | 2302 | static inline struct drm_plane *drm_plane_find(struct drm_device *dev, |
3002 | uint32_t id) | 2303 | uint32_t id) |
3003 | { | 2304 | { |
@@ -3022,22 +2323,6 @@ static inline struct drm_encoder *drm_encoder_find(struct drm_device *dev, | |||
3022 | return mo ? obj_to_encoder(mo) : NULL; | 2323 | return mo ? obj_to_encoder(mo) : NULL; |
3023 | } | 2324 | } |
3024 | 2325 | ||
3025 | /** | ||
3026 | * drm_connector_lookup - lookup connector object | ||
3027 | * @dev: DRM device | ||
3028 | * @id: connector object id | ||
3029 | * | ||
3030 | * This function looks up the connector object specified by id | ||
3031 | * add takes a reference to it. | ||
3032 | */ | ||
3033 | static inline struct drm_connector *drm_connector_lookup(struct drm_device *dev, | ||
3034 | uint32_t id) | ||
3035 | { | ||
3036 | struct drm_mode_object *mo; | ||
3037 | mo = drm_mode_object_find(dev, id, DRM_MODE_OBJECT_CONNECTOR); | ||
3038 | return mo ? obj_to_connector(mo) : NULL; | ||
3039 | } | ||
3040 | |||
3041 | static inline struct drm_property *drm_property_find(struct drm_device *dev, | 2326 | static inline struct drm_property *drm_property_find(struct drm_device *dev, |
3042 | uint32_t id) | 2327 | uint32_t id) |
3043 | { | 2328 | { |
@@ -3065,61 +2350,6 @@ static inline uint32_t drm_color_lut_extract(uint32_t user_input, | |||
3065 | return clamp_val(val, 0, max); | 2350 | return clamp_val(val, 0, max); |
3066 | } | 2351 | } |
3067 | 2352 | ||
3068 | /** | ||
3069 | * drm_framebuffer_reference - incr the fb refcnt | ||
3070 | * @fb: framebuffer | ||
3071 | * | ||
3072 | * This functions increments the fb's refcount. | ||
3073 | */ | ||
3074 | static inline void drm_framebuffer_reference(struct drm_framebuffer *fb) | ||
3075 | { | ||
3076 | drm_mode_object_reference(&fb->base); | ||
3077 | } | ||
3078 | |||
3079 | /** | ||
3080 | * drm_framebuffer_unreference - unref a framebuffer | ||
3081 | * @fb: framebuffer to unref | ||
3082 | * | ||
3083 | * This functions decrements the fb's refcount and frees it if it drops to zero. | ||
3084 | */ | ||
3085 | static inline void drm_framebuffer_unreference(struct drm_framebuffer *fb) | ||
3086 | { | ||
3087 | drm_mode_object_unreference(&fb->base); | ||
3088 | } | ||
3089 | |||
3090 | /** | ||
3091 | * drm_framebuffer_read_refcount - read the framebuffer reference count. | ||
3092 | * @fb: framebuffer | ||
3093 | * | ||
3094 | * This functions returns the framebuffer's reference count. | ||
3095 | */ | ||
3096 | static inline uint32_t drm_framebuffer_read_refcount(struct drm_framebuffer *fb) | ||
3097 | { | ||
3098 | return atomic_read(&fb->base.refcount.refcount); | ||
3099 | } | ||
3100 | |||
3101 | /** | ||
3102 | * drm_connector_reference - incr the connector refcnt | ||
3103 | * @connector: connector | ||
3104 | * | ||
3105 | * This function increments the connector's refcount. | ||
3106 | */ | ||
3107 | static inline void drm_connector_reference(struct drm_connector *connector) | ||
3108 | { | ||
3109 | drm_mode_object_reference(&connector->base); | ||
3110 | } | ||
3111 | |||
3112 | /** | ||
3113 | * drm_connector_unreference - unref a connector | ||
3114 | * @connector: connector to unref | ||
3115 | * | ||
3116 | * This function decrements the connector's refcount and frees it if it drops to zero. | ||
3117 | */ | ||
3118 | static inline void drm_connector_unreference(struct drm_connector *connector) | ||
3119 | { | ||
3120 | drm_mode_object_unreference(&connector->base); | ||
3121 | } | ||
3122 | |||
3123 | /* Plane list iterator for legacy (overlay only) planes. */ | 2353 | /* Plane list iterator for legacy (overlay only) planes. */ |
3124 | #define drm_for_each_legacy_plane(plane, dev) \ | 2354 | #define drm_for_each_legacy_plane(plane, dev) \ |
3125 | list_for_each_entry(plane, &(dev)->mode_config.plane_list, head) \ | 2355 | list_for_each_entry(plane, &(dev)->mode_config.plane_list, head) \ |
diff --git a/include/drm/drm_crtc_helper.h b/include/drm/drm_crtc_helper.h index 4b37afa2b73b..982c299e435a 100644 --- a/include/drm/drm_crtc_helper.h +++ b/include/drm/drm_crtc_helper.h | |||
@@ -41,6 +41,7 @@ | |||
41 | 41 | ||
42 | #include <drm/drm_crtc.h> | 42 | #include <drm/drm_crtc.h> |
43 | #include <drm/drm_modeset_helper_vtables.h> | 43 | #include <drm/drm_modeset_helper_vtables.h> |
44 | #include <drm/drm_modeset_helper.h> | ||
44 | 45 | ||
45 | extern void drm_helper_disable_unused_functions(struct drm_device *dev); | 46 | extern void drm_helper_disable_unused_functions(struct drm_device *dev); |
46 | extern int drm_crtc_helper_set_config(struct drm_mode_set *set); | 47 | extern int drm_crtc_helper_set_config(struct drm_mode_set *set); |
@@ -53,11 +54,6 @@ extern bool drm_helper_encoder_in_use(struct drm_encoder *encoder); | |||
53 | 54 | ||
54 | extern int drm_helper_connector_dpms(struct drm_connector *connector, int mode); | 55 | extern int drm_helper_connector_dpms(struct drm_connector *connector, int mode); |
55 | 56 | ||
56 | extern void drm_helper_move_panel_connectors_to_head(struct drm_device *); | ||
57 | |||
58 | extern void drm_helper_mode_fill_fb_struct(struct drm_framebuffer *fb, | ||
59 | const struct drm_mode_fb_cmd2 *mode_cmd); | ||
60 | |||
61 | extern void drm_helper_resume_force_mode(struct drm_device *dev); | 57 | extern void drm_helper_resume_force_mode(struct drm_device *dev); |
62 | 58 | ||
63 | int drm_helper_crtc_mode_set(struct drm_crtc *crtc, struct drm_display_mode *mode, | 59 | int drm_helper_crtc_mode_set(struct drm_crtc *crtc, struct drm_display_mode *mode, |
diff --git a/include/drm/drm_fb_helper.h b/include/drm/drm_fb_helper.h index 130c324f1aee..edc6cfd3aa34 100644 --- a/include/drm/drm_fb_helper.h +++ b/include/drm/drm_fb_helper.h | |||
@@ -177,6 +177,7 @@ struct drm_fb_helper_connector { | |||
177 | * the screen buffer | 177 | * the screen buffer |
178 | * @dirty_lock: spinlock protecting @dirty_clip | 178 | * @dirty_lock: spinlock protecting @dirty_clip |
179 | * @dirty_work: worker used to flush the framebuffer | 179 | * @dirty_work: worker used to flush the framebuffer |
180 | * @resume_work: worker used during resume if the console lock is already taken | ||
180 | * | 181 | * |
181 | * This is the main structure used by the fbdev helpers. Drivers supporting | 182 | * This is the main structure used by the fbdev helpers. Drivers supporting |
182 | * fbdev emulation should embedded this into their overall driver structure. | 183 | * fbdev emulation should embedded this into their overall driver structure. |
@@ -197,6 +198,7 @@ struct drm_fb_helper { | |||
197 | struct drm_clip_rect dirty_clip; | 198 | struct drm_clip_rect dirty_clip; |
198 | spinlock_t dirty_lock; | 199 | spinlock_t dirty_lock; |
199 | struct work_struct dirty_work; | 200 | struct work_struct dirty_work; |
201 | struct work_struct resume_work; | ||
200 | 202 | ||
201 | /** | 203 | /** |
202 | * @kernel_fb_list: | 204 | * @kernel_fb_list: |
@@ -216,7 +218,6 @@ struct drm_fb_helper { | |||
216 | }; | 218 | }; |
217 | 219 | ||
218 | #ifdef CONFIG_DRM_FBDEV_EMULATION | 220 | #ifdef CONFIG_DRM_FBDEV_EMULATION |
219 | int drm_fb_helper_modinit(void); | ||
220 | void drm_fb_helper_prepare(struct drm_device *dev, struct drm_fb_helper *helper, | 221 | void drm_fb_helper_prepare(struct drm_device *dev, struct drm_fb_helper *helper, |
221 | const struct drm_fb_helper_funcs *funcs); | 222 | const struct drm_fb_helper_funcs *funcs); |
222 | int drm_fb_helper_init(struct drm_device *dev, | 223 | int drm_fb_helper_init(struct drm_device *dev, |
@@ -264,7 +265,9 @@ void drm_fb_helper_cfb_copyarea(struct fb_info *info, | |||
264 | void drm_fb_helper_cfb_imageblit(struct fb_info *info, | 265 | void drm_fb_helper_cfb_imageblit(struct fb_info *info, |
265 | const struct fb_image *image); | 266 | const struct fb_image *image); |
266 | 267 | ||
267 | void drm_fb_helper_set_suspend(struct drm_fb_helper *fb_helper, int state); | 268 | void drm_fb_helper_set_suspend(struct drm_fb_helper *fb_helper, bool suspend); |
269 | void drm_fb_helper_set_suspend_unlocked(struct drm_fb_helper *fb_helper, | ||
270 | bool suspend); | ||
268 | 271 | ||
269 | int drm_fb_helper_setcmap(struct fb_cmap *cmap, struct fb_info *info); | 272 | int drm_fb_helper_setcmap(struct fb_cmap *cmap, struct fb_info *info); |
270 | 273 | ||
@@ -283,12 +286,6 @@ drm_pick_cmdline_mode(struct drm_fb_helper_connector *fb_helper_conn, | |||
283 | int drm_fb_helper_add_one_connector(struct drm_fb_helper *fb_helper, struct drm_connector *connector); | 286 | int drm_fb_helper_add_one_connector(struct drm_fb_helper *fb_helper, struct drm_connector *connector); |
284 | int drm_fb_helper_remove_one_connector(struct drm_fb_helper *fb_helper, | 287 | int drm_fb_helper_remove_one_connector(struct drm_fb_helper *fb_helper, |
285 | struct drm_connector *connector); | 288 | struct drm_connector *connector); |
286 | static inline int | ||
287 | drm_fb_helper_remove_conflicting_framebuffers(struct apertures_struct *a, | ||
288 | const char *name, bool primary) | ||
289 | { | ||
290 | return remove_conflicting_framebuffers(a, name, primary); | ||
291 | } | ||
292 | #else | 289 | #else |
293 | static inline int drm_fb_helper_modinit(void) | 290 | static inline int drm_fb_helper_modinit(void) |
294 | { | 291 | { |
@@ -424,7 +421,12 @@ static inline void drm_fb_helper_cfb_imageblit(struct fb_info *info, | |||
424 | } | 421 | } |
425 | 422 | ||
426 | static inline void drm_fb_helper_set_suspend(struct drm_fb_helper *fb_helper, | 423 | static inline void drm_fb_helper_set_suspend(struct drm_fb_helper *fb_helper, |
427 | int state) | 424 | bool suspend) |
425 | { | ||
426 | } | ||
427 | |||
428 | static inline void | ||
429 | drm_fb_helper_set_suspend_unlocked(struct drm_fb_helper *fb_helper, bool suspend) | ||
428 | { | 430 | { |
429 | } | 431 | } |
430 | 432 | ||
@@ -483,11 +485,17 @@ drm_fb_helper_remove_one_connector(struct drm_fb_helper *fb_helper, | |||
483 | return 0; | 485 | return 0; |
484 | } | 486 | } |
485 | 487 | ||
488 | #endif | ||
489 | |||
486 | static inline int | 490 | static inline int |
487 | drm_fb_helper_remove_conflicting_framebuffers(struct apertures_struct *a, | 491 | drm_fb_helper_remove_conflicting_framebuffers(struct apertures_struct *a, |
488 | const char *name, bool primary) | 492 | const char *name, bool primary) |
489 | { | 493 | { |
494 | #if IS_ENABLED(CONFIG_FB) | ||
495 | return remove_conflicting_framebuffers(a, name, primary); | ||
496 | #else | ||
490 | return 0; | 497 | return 0; |
491 | } | ||
492 | #endif | 498 | #endif |
499 | } | ||
500 | |||
493 | #endif | 501 | #endif |
diff --git a/include/drm/drm_fourcc.h b/include/drm/drm_fourcc.h index 7f90a396cf2b..b106337de1bf 100644 --- a/include/drm/drm_fourcc.h +++ b/include/drm/drm_fourcc.h | |||
@@ -32,6 +32,6 @@ int drm_format_horz_chroma_subsampling(uint32_t format); | |||
32 | int drm_format_vert_chroma_subsampling(uint32_t format); | 32 | int drm_format_vert_chroma_subsampling(uint32_t format); |
33 | int drm_format_plane_width(int width, uint32_t format, int plane); | 33 | int drm_format_plane_width(int width, uint32_t format, int plane); |
34 | int drm_format_plane_height(int height, uint32_t format, int plane); | 34 | int drm_format_plane_height(int height, uint32_t format, int plane); |
35 | const char *drm_get_format_name(uint32_t format); | 35 | char *drm_get_format_name(uint32_t format) __malloc; |
36 | 36 | ||
37 | #endif /* __DRM_FOURCC_H__ */ | 37 | #endif /* __DRM_FOURCC_H__ */ |
diff --git a/include/drm/drm_framebuffer.h b/include/drm/drm_framebuffer.h new file mode 100644 index 000000000000..50deb40d3bfd --- /dev/null +++ b/include/drm/drm_framebuffer.h | |||
@@ -0,0 +1,250 @@ | |||
1 | /* | ||
2 | * Copyright (c) 2016 Intel Corporation | ||
3 | * | ||
4 | * Permission to use, copy, modify, distribute, and sell this software and its | ||
5 | * documentation for any purpose is hereby granted without fee, provided that | ||
6 | * the above copyright notice appear in all copies and that both that copyright | ||
7 | * notice and this permission notice appear in supporting documentation, and | ||
8 | * that the name of the copyright holders not be used in advertising or | ||
9 | * publicity pertaining to distribution of the software without specific, | ||
10 | * written prior permission. The copyright holders make no representations | ||
11 | * about the suitability of this software for any purpose. It is provided "as | ||
12 | * is" without express or implied warranty. | ||
13 | * | ||
14 | * THE COPYRIGHT HOLDERS DISCLAIM ALL WARRANTIES WITH REGARD TO THIS SOFTWARE, | ||
15 | * INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS, IN NO | ||
16 | * EVENT SHALL THE COPYRIGHT HOLDERS BE LIABLE FOR ANY SPECIAL, INDIRECT OR | ||
17 | * CONSEQUENTIAL DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM LOSS OF USE, | ||
18 | * DATA OR PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER | ||
19 | * TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR PERFORMANCE | ||
20 | * OF THIS SOFTWARE. | ||
21 | */ | ||
22 | |||
23 | #ifndef __DRM_FRAMEBUFFER_H__ | ||
24 | #define __DRM_FRAMEBUFFER_H__ | ||
25 | |||
26 | #include <linux/list.h> | ||
27 | #include <linux/ctype.h> | ||
28 | #include <drm/drm_modeset.h> | ||
29 | |||
30 | struct drm_framebuffer; | ||
31 | struct drm_file; | ||
32 | struct drm_device; | ||
33 | |||
34 | /** | ||
35 | * struct drm_framebuffer_funcs - framebuffer hooks | ||
36 | */ | ||
37 | struct drm_framebuffer_funcs { | ||
38 | /** | ||
39 | * @destroy: | ||
40 | * | ||
41 | * Clean up framebuffer resources, specifically also unreference the | ||
42 | * backing storage. The core guarantees to call this function for every | ||
43 | * framebuffer successfully created by ->fb_create() in | ||
44 | * &drm_mode_config_funcs. Drivers must also call | ||
45 | * drm_framebuffer_cleanup() to release DRM core resources for this | ||
46 | * framebuffer. | ||
47 | */ | ||
48 | void (*destroy)(struct drm_framebuffer *framebuffer); | ||
49 | |||
50 | /** | ||
51 | * @create_handle: | ||
52 | * | ||
53 | * Create a buffer handle in the driver-specific buffer manager (either | ||
54 | * GEM or TTM) valid for the passed-in struct &drm_file. This is used by | ||
55 | * the core to implement the GETFB IOCTL, which returns (for | ||
56 | * sufficiently priviledged user) also a native buffer handle. This can | ||
57 | * be used for seamless transitions between modesetting clients by | ||
58 | * copying the current screen contents to a private buffer and blending | ||
59 | * between that and the new contents. | ||
60 | * | ||
61 | * GEM based drivers should call drm_gem_handle_create() to create the | ||
62 | * handle. | ||
63 | * | ||
64 | * RETURNS: | ||
65 | * | ||
66 | * 0 on success or a negative error code on failure. | ||
67 | */ | ||
68 | int (*create_handle)(struct drm_framebuffer *fb, | ||
69 | struct drm_file *file_priv, | ||
70 | unsigned int *handle); | ||
71 | /** | ||
72 | * @dirty: | ||
73 | * | ||
74 | * Optional callback for the dirty fb IOCTL. | ||
75 | * | ||
76 | * Userspace can notify the driver via this callback that an area of the | ||
77 | * framebuffer has changed and should be flushed to the display | ||
78 | * hardware. This can also be used internally, e.g. by the fbdev | ||
79 | * emulation, though that's not the case currently. | ||
80 | * | ||
81 | * See documentation in drm_mode.h for the struct drm_mode_fb_dirty_cmd | ||
82 | * for more information as all the semantics and arguments have a one to | ||
83 | * one mapping on this function. | ||
84 | * | ||
85 | * RETURNS: | ||
86 | * | ||
87 | * 0 on success or a negative error code on failure. | ||
88 | */ | ||
89 | int (*dirty)(struct drm_framebuffer *framebuffer, | ||
90 | struct drm_file *file_priv, unsigned flags, | ||
91 | unsigned color, struct drm_clip_rect *clips, | ||
92 | unsigned num_clips); | ||
93 | }; | ||
94 | |||
95 | /** | ||
96 | * struct drm_framebuffer - frame buffer object | ||
97 | * | ||
98 | * Note that the fb is refcounted for the benefit of driver internals, | ||
99 | * for example some hw, disabling a CRTC/plane is asynchronous, and | ||
100 | * scanout does not actually complete until the next vblank. So some | ||
101 | * cleanup (like releasing the reference(s) on the backing GEM bo(s)) | ||
102 | * should be deferred. In cases like this, the driver would like to | ||
103 | * hold a ref to the fb even though it has already been removed from | ||
104 | * userspace perspective. See drm_framebuffer_reference() and | ||
105 | * drm_framebuffer_unreference(). | ||
106 | * | ||
107 | * The refcount is stored inside the mode object @base. | ||
108 | */ | ||
109 | struct drm_framebuffer { | ||
110 | /** | ||
111 | * @dev: DRM device this framebuffer belongs to | ||
112 | */ | ||
113 | struct drm_device *dev; | ||
114 | /** | ||
115 | * @head: Place on the dev->mode_config.fb_list, access protected by | ||
116 | * dev->mode_config.fb_lock. | ||
117 | */ | ||
118 | struct list_head head; | ||
119 | |||
120 | /** | ||
121 | * @base: base modeset object structure, contains the reference count. | ||
122 | */ | ||
123 | struct drm_mode_object base; | ||
124 | /** | ||
125 | * @funcs: framebuffer vfunc table | ||
126 | */ | ||
127 | const struct drm_framebuffer_funcs *funcs; | ||
128 | /** | ||
129 | * @pitches: Line stride per buffer. For userspace created object this | ||
130 | * is copied from drm_mode_fb_cmd2. | ||
131 | */ | ||
132 | unsigned int pitches[4]; | ||
133 | /** | ||
134 | * @offsets: Offset from buffer start to the actual pixel data in bytes, | ||
135 | * per buffer. For userspace created object this is copied from | ||
136 | * drm_mode_fb_cmd2. | ||
137 | * | ||
138 | * Note that this is a linear offset and does not take into account | ||
139 | * tiling or buffer laytou per @modifier. It meant to be used when the | ||
140 | * actual pixel data for this framebuffer plane starts at an offset, | ||
141 | * e.g. when multiple planes are allocated within the same backing | ||
142 | * storage buffer object. For tiled layouts this generally means it | ||
143 | * @offsets must at least be tile-size aligned, but hardware often has | ||
144 | * stricter requirements. | ||
145 | * | ||
146 | * This should not be used to specifiy x/y pixel offsets into the buffer | ||
147 | * data (even for linear buffers). Specifying an x/y pixel offset is | ||
148 | * instead done through the source rectangle in struct &drm_plane_state. | ||
149 | */ | ||
150 | unsigned int offsets[4]; | ||
151 | /** | ||
152 | * @modifier: Data layout modifier, per buffer. This is used to describe | ||
153 | * tiling, or also special layouts (like compression) of auxiliary | ||
154 | * buffers. For userspace created object this is copied from | ||
155 | * drm_mode_fb_cmd2. | ||
156 | */ | ||
157 | uint64_t modifier[4]; | ||
158 | /** | ||
159 | * @width: Logical width of the visible area of the framebuffer, in | ||
160 | * pixels. | ||
161 | */ | ||
162 | unsigned int width; | ||
163 | /** | ||
164 | * @height: Logical height of the visible area of the framebuffer, in | ||
165 | * pixels. | ||
166 | */ | ||
167 | unsigned int height; | ||
168 | /** | ||
169 | * @depth: Depth in bits per pixel for RGB formats. 0 for everything | ||
170 | * else. Legacy information derived from @pixel_format, it's suggested to use | ||
171 | * the DRM FOURCC codes and helper functions directly instead. | ||
172 | */ | ||
173 | unsigned int depth; | ||
174 | /** | ||
175 | * @bits_per_pixel: Storage used bits per pixel for RGB formats. 0 for | ||
176 | * everything else. Legacy information derived from @pixel_format, it's | ||
177 | * suggested to use the DRM FOURCC codes and helper functions directly | ||
178 | * instead. | ||
179 | */ | ||
180 | int bits_per_pixel; | ||
181 | /** | ||
182 | * @flags: Framebuffer flags like DRM_MODE_FB_INTERLACED or | ||
183 | * DRM_MODE_FB_MODIFIERS. | ||
184 | */ | ||
185 | int flags; | ||
186 | /** | ||
187 | * @pixel_format: DRM FOURCC code describing the pixel format. | ||
188 | */ | ||
189 | uint32_t pixel_format; /* fourcc format */ | ||
190 | /** | ||
191 | * @hot_x: X coordinate of the cursor hotspot. Used by the legacy cursor | ||
192 | * IOCTL when the driver supports cursor through a DRM_PLANE_TYPE_CURSOR | ||
193 | * universal plane. | ||
194 | */ | ||
195 | int hot_x; | ||
196 | /** | ||
197 | * @hot_y: Y coordinate of the cursor hotspot. Used by the legacy cursor | ||
198 | * IOCTL when the driver supports cursor through a DRM_PLANE_TYPE_CURSOR | ||
199 | * universal plane. | ||
200 | */ | ||
201 | int hot_y; | ||
202 | /** | ||
203 | * @filp_head: Placed on struct &drm_file fbs list_head, protected by | ||
204 | * fbs_lock in the same structure. | ||
205 | */ | ||
206 | struct list_head filp_head; | ||
207 | }; | ||
208 | |||
209 | int drm_framebuffer_init(struct drm_device *dev, | ||
210 | struct drm_framebuffer *fb, | ||
211 | const struct drm_framebuffer_funcs *funcs); | ||
212 | struct drm_framebuffer *drm_framebuffer_lookup(struct drm_device *dev, | ||
213 | uint32_t id); | ||
214 | void drm_framebuffer_remove(struct drm_framebuffer *fb); | ||
215 | void drm_framebuffer_cleanup(struct drm_framebuffer *fb); | ||
216 | void drm_framebuffer_unregister_private(struct drm_framebuffer *fb); | ||
217 | |||
218 | /** | ||
219 | * drm_framebuffer_reference - incr the fb refcnt | ||
220 | * @fb: framebuffer | ||
221 | * | ||
222 | * This functions increments the fb's refcount. | ||
223 | */ | ||
224 | static inline void drm_framebuffer_reference(struct drm_framebuffer *fb) | ||
225 | { | ||
226 | drm_mode_object_reference(&fb->base); | ||
227 | } | ||
228 | |||
229 | /** | ||
230 | * drm_framebuffer_unreference - unref a framebuffer | ||
231 | * @fb: framebuffer to unref | ||
232 | * | ||
233 | * This functions decrements the fb's refcount and frees it if it drops to zero. | ||
234 | */ | ||
235 | static inline void drm_framebuffer_unreference(struct drm_framebuffer *fb) | ||
236 | { | ||
237 | drm_mode_object_unreference(&fb->base); | ||
238 | } | ||
239 | |||
240 | /** | ||
241 | * drm_framebuffer_read_refcount - read the framebuffer reference count. | ||
242 | * @fb: framebuffer | ||
243 | * | ||
244 | * This functions returns the framebuffer's reference count. | ||
245 | */ | ||
246 | static inline uint32_t drm_framebuffer_read_refcount(struct drm_framebuffer *fb) | ||
247 | { | ||
248 | return atomic_read(&fb->base.refcount.refcount); | ||
249 | } | ||
250 | #endif | ||
diff --git a/include/drm/drm_gem.h b/include/drm/drm_gem.h index fca1cd1b9c26..9f63736e6163 100644 --- a/include/drm/drm_gem.h +++ b/include/drm/drm_gem.h | |||
@@ -210,8 +210,8 @@ drm_gem_object_reference(struct drm_gem_object *obj) | |||
210 | * drm_gem_object_unreference_unlocked(). | 210 | * drm_gem_object_unreference_unlocked(). |
211 | * | 211 | * |
212 | * Drivers should never call this directly in their code. Instead they should | 212 | * Drivers should never call this directly in their code. Instead they should |
213 | * wrap it up into a driver_gem_object_unreference(struct driver_gem_object | 213 | * wrap it up into a ``driver_gem_object_unreference(struct driver_gem_object |
214 | * *obj) wrapper function, and use that. Shared code should never call this, to | 214 | * *obj)`` wrapper function, and use that. Shared code should never call this, to |
215 | * avoid breaking drivers by accident which still depend upon dev->struct_mutex | 215 | * avoid breaking drivers by accident which still depend upon dev->struct_mutex |
216 | * locking. | 216 | * locking. |
217 | */ | 217 | */ |
diff --git a/include/drm/drm_modes.h b/include/drm/drm_modes.h index 48e1a56ea283..1621e9b32330 100644 --- a/include/drm/drm_modes.h +++ b/include/drm/drm_modes.h | |||
@@ -27,6 +27,9 @@ | |||
27 | #ifndef __DRM_MODES_H__ | 27 | #ifndef __DRM_MODES_H__ |
28 | #define __DRM_MODES_H__ | 28 | #define __DRM_MODES_H__ |
29 | 29 | ||
30 | #include <drm/drm_modeset.h> | ||
31 | #include <drm/drm_connector.h> | ||
32 | |||
30 | /* | 33 | /* |
31 | * Note on terminology: here, for brevity and convenience, we refer to connector | 34 | * Note on terminology: here, for brevity and convenience, we refer to connector |
32 | * control chips as 'CRTCs'. They can control any type of connector, VGA, LVDS, | 35 | * control chips as 'CRTCs'. They can control any type of connector, VGA, LVDS, |
@@ -400,21 +403,6 @@ struct drm_display_mode { | |||
400 | enum hdmi_picture_aspect picture_aspect_ratio; | 403 | enum hdmi_picture_aspect picture_aspect_ratio; |
401 | }; | 404 | }; |
402 | 405 | ||
403 | /* mode specified on the command line */ | ||
404 | struct drm_cmdline_mode { | ||
405 | bool specified; | ||
406 | bool refresh_specified; | ||
407 | bool bpp_specified; | ||
408 | int xres, yres; | ||
409 | int bpp; | ||
410 | int refresh; | ||
411 | bool rb; | ||
412 | bool interlace; | ||
413 | bool cvt; | ||
414 | bool margins; | ||
415 | enum drm_connector_force force; | ||
416 | }; | ||
417 | |||
418 | /** | 406 | /** |
419 | * drm_mode_is_stereo - check for stereo mode flags | 407 | * drm_mode_is_stereo - check for stereo mode flags |
420 | * @mode: drm_display_mode to check | 408 | * @mode: drm_display_mode to check |
diff --git a/include/drm/drm_modeset.h b/include/drm/drm_modeset.h new file mode 100644 index 000000000000..fe910d5efe12 --- /dev/null +++ b/include/drm/drm_modeset.h | |||
@@ -0,0 +1,70 @@ | |||
1 | /* | ||
2 | * Copyright (c) 2016 Intel Corporation | ||
3 | * | ||
4 | * Permission to use, copy, modify, distribute, and sell this software and its | ||
5 | * documentation for any purpose is hereby granted without fee, provided that | ||
6 | * the above copyright notice appear in all copies and that both that copyright | ||
7 | * notice and this permission notice appear in supporting documentation, and | ||
8 | * that the name of the copyright holders not be used in advertising or | ||
9 | * publicity pertaining to distribution of the software without specific, | ||
10 | * written prior permission. The copyright holders make no representations | ||
11 | * about the suitability of this software for any purpose. It is provided "as | ||
12 | * is" without express or implied warranty. | ||
13 | * | ||
14 | * THE COPYRIGHT HOLDERS DISCLAIM ALL WARRANTIES WITH REGARD TO THIS SOFTWARE, | ||
15 | * INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS, IN NO | ||
16 | * EVENT SHALL THE COPYRIGHT HOLDERS BE LIABLE FOR ANY SPECIAL, INDIRECT OR | ||
17 | * CONSEQUENTIAL DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM LOSS OF USE, | ||
18 | * DATA OR PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER | ||
19 | * TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR PERFORMANCE | ||
20 | * OF THIS SOFTWARE. | ||
21 | */ | ||
22 | |||
23 | #ifndef __DRM_MODESET_H__ | ||
24 | #define __DRM_MODESET_H__ | ||
25 | |||
26 | #include <linux/kref.h> | ||
27 | struct drm_object_properties; | ||
28 | struct drm_property; | ||
29 | |||
30 | struct drm_mode_object { | ||
31 | uint32_t id; | ||
32 | uint32_t type; | ||
33 | struct drm_object_properties *properties; | ||
34 | struct kref refcount; | ||
35 | void (*free_cb)(struct kref *kref); | ||
36 | }; | ||
37 | |||
38 | #define DRM_OBJECT_MAX_PROPERTY 24 | ||
39 | struct drm_object_properties { | ||
40 | int count, atomic_count; | ||
41 | /* NOTE: if we ever start dynamically destroying properties (ie. | ||
42 | * not at drm_mode_config_cleanup() time), then we'd have to do | ||
43 | * a better job of detaching property from mode objects to avoid | ||
44 | * dangling property pointers: | ||
45 | */ | ||
46 | struct drm_property *properties[DRM_OBJECT_MAX_PROPERTY]; | ||
47 | /* do not read/write values directly, but use drm_object_property_get_value() | ||
48 | * and drm_object_property_set_value(): | ||
49 | */ | ||
50 | uint64_t values[DRM_OBJECT_MAX_PROPERTY]; | ||
51 | }; | ||
52 | |||
53 | /* Avoid boilerplate. I'm tired of typing. */ | ||
54 | #define DRM_ENUM_NAME_FN(fnname, list) \ | ||
55 | const char *fnname(int val) \ | ||
56 | { \ | ||
57 | int i; \ | ||
58 | for (i = 0; i < ARRAY_SIZE(list); i++) { \ | ||
59 | if (list[i].type == val) \ | ||
60 | return list[i].name; \ | ||
61 | } \ | ||
62 | return "(unknown)"; \ | ||
63 | } | ||
64 | |||
65 | struct drm_mode_object *drm_mode_object_find(struct drm_device *dev, | ||
66 | uint32_t id, uint32_t type); | ||
67 | void drm_mode_object_reference(struct drm_mode_object *obj); | ||
68 | void drm_mode_object_unreference(struct drm_mode_object *obj); | ||
69 | |||
70 | #endif | ||
diff --git a/include/drm/drm_modeset_helper.h b/include/drm/drm_modeset_helper.h new file mode 100644 index 000000000000..b8051d5abe10 --- /dev/null +++ b/include/drm/drm_modeset_helper.h | |||
@@ -0,0 +1,36 @@ | |||
1 | /* | ||
2 | * Copyright (c) 2016 Intel Corporation | ||
3 | * | ||
4 | * Permission to use, copy, modify, distribute, and sell this software and its | ||
5 | * documentation for any purpose is hereby granted without fee, provided that | ||
6 | * the above copyright notice appear in all copies and that both that copyright | ||
7 | * notice and this permission notice appear in supporting documentation, and | ||
8 | * that the name of the copyright holders not be used in advertising or | ||
9 | * publicity pertaining to distribution of the software without specific, | ||
10 | * written prior permission. The copyright holders make no representations | ||
11 | * about the suitability of this software for any purpose. It is provided "as | ||
12 | * is" without express or implied warranty. | ||
13 | * | ||
14 | * THE COPYRIGHT HOLDERS DISCLAIM ALL WARRANTIES WITH REGARD TO THIS SOFTWARE, | ||
15 | * INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS, IN NO | ||
16 | * EVENT SHALL THE COPYRIGHT HOLDERS BE LIABLE FOR ANY SPECIAL, INDIRECT OR | ||
17 | * CONSEQUENTIAL DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM LOSS OF USE, | ||
18 | * DATA OR PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER | ||
19 | * TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR PERFORMANCE | ||
20 | * OF THIS SOFTWARE. | ||
21 | */ | ||
22 | |||
23 | #ifndef __DRM_KMS_HELPER_H__ | ||
24 | #define __DRM_KMS_HELPER_H__ | ||
25 | |||
26 | #include <drm/drmP.h> | ||
27 | |||
28 | void drm_helper_move_panel_connectors_to_head(struct drm_device *); | ||
29 | |||
30 | void drm_helper_mode_fill_fb_struct(struct drm_framebuffer *fb, | ||
31 | const struct drm_mode_fb_cmd2 *mode_cmd); | ||
32 | |||
33 | int drm_crtc_init(struct drm_device *dev, struct drm_crtc *crtc, | ||
34 | const struct drm_crtc_funcs *funcs); | ||
35 | |||
36 | #endif | ||
diff --git a/include/drm/drm_modeset_helper_vtables.h b/include/drm/drm_modeset_helper_vtables.h index 686feec6b4c8..6c8d3dad66ec 100644 --- a/include/drm/drm_modeset_helper_vtables.h +++ b/include/drm/drm_modeset_helper_vtables.h | |||
@@ -855,7 +855,7 @@ struct drm_plane_helper_funcs { | |||
855 | * everything else must complete successfully. | 855 | * everything else must complete successfully. |
856 | */ | 856 | */ |
857 | int (*prepare_fb)(struct drm_plane *plane, | 857 | int (*prepare_fb)(struct drm_plane *plane, |
858 | const struct drm_plane_state *new_state); | 858 | struct drm_plane_state *new_state); |
859 | /** | 859 | /** |
860 | * @cleanup_fb: | 860 | * @cleanup_fb: |
861 | * | 861 | * |
@@ -866,7 +866,7 @@ struct drm_plane_helper_funcs { | |||
866 | * transitional plane helpers, but it is optional. | 866 | * transitional plane helpers, but it is optional. |
867 | */ | 867 | */ |
868 | void (*cleanup_fb)(struct drm_plane *plane, | 868 | void (*cleanup_fb)(struct drm_plane *plane, |
869 | const struct drm_plane_state *old_state); | 869 | struct drm_plane_state *old_state); |
870 | 870 | ||
871 | /** | 871 | /** |
872 | * @atomic_check: | 872 | * @atomic_check: |
diff --git a/include/drm/drm_plane_helper.h b/include/drm/drm_plane_helper.h index fbc8ecb3e5e8..c18959685c06 100644 --- a/include/drm/drm_plane_helper.h +++ b/include/drm/drm_plane_helper.h | |||
@@ -27,6 +27,7 @@ | |||
27 | #include <drm/drm_rect.h> | 27 | #include <drm/drm_rect.h> |
28 | #include <drm/drm_crtc.h> | 28 | #include <drm/drm_crtc.h> |
29 | #include <drm/drm_modeset_helper_vtables.h> | 29 | #include <drm/drm_modeset_helper_vtables.h> |
30 | #include <drm/drm_modeset_helper.h> | ||
30 | 31 | ||
31 | /* | 32 | /* |
32 | * Drivers that don't allow primary plane scaling may pass this macro in place | 33 | * Drivers that don't allow primary plane scaling may pass this macro in place |
@@ -37,9 +38,6 @@ | |||
37 | */ | 38 | */ |
38 | #define DRM_PLANE_HELPER_NO_SCALING (1<<16) | 39 | #define DRM_PLANE_HELPER_NO_SCALING (1<<16) |
39 | 40 | ||
40 | int drm_crtc_init(struct drm_device *dev, struct drm_crtc *crtc, | ||
41 | const struct drm_crtc_funcs *funcs); | ||
42 | |||
43 | int drm_plane_helper_check_state(struct drm_plane_state *state, | 41 | int drm_plane_helper_check_state(struct drm_plane_state *state, |
44 | const struct drm_rect *clip, | 42 | const struct drm_rect *clip, |
45 | int min_scale, int max_scale, | 43 | int min_scale, int max_scale, |
diff --git a/include/linux/vgaarb.h b/include/linux/vgaarb.h index 8c3b412d84df..ee162e3e879b 100644 --- a/include/linux/vgaarb.h +++ b/include/linux/vgaarb.h | |||
@@ -73,34 +73,6 @@ static inline void vga_set_legacy_decoding(struct pci_dev *pdev, | |||
73 | unsigned int decodes) { }; | 73 | unsigned int decodes) { }; |
74 | #endif | 74 | #endif |
75 | 75 | ||
76 | /** | ||
77 | * vga_get - acquire & locks VGA resources | ||
78 | * | ||
79 | * @pdev: pci device of the VGA card or NULL for the system default | ||
80 | * @rsrc: bit mask of resources to acquire and lock | ||
81 | * @interruptible: blocking should be interruptible by signals ? | ||
82 | * | ||
83 | * This function acquires VGA resources for the given | ||
84 | * card and mark those resources locked. If the resource requested | ||
85 | * are "normal" (and not legacy) resources, the arbiter will first check | ||
86 | * whether the card is doing legacy decoding for that type of resource. If | ||
87 | * yes, the lock is "converted" into a legacy resource lock. | ||
88 | * The arbiter will first look for all VGA cards that might conflict | ||
89 | * and disable their IOs and/or Memory access, including VGA forwarding | ||
90 | * on P2P bridges if necessary, so that the requested resources can | ||
91 | * be used. Then, the card is marked as locking these resources and | ||
92 | * the IO and/or Memory accesse are enabled on the card (including | ||
93 | * VGA forwarding on parent P2P bridges if any). | ||
94 | * This function will block if some conflicting card is already locking | ||
95 | * one of the required resources (or any resource on a different bus | ||
96 | * segment, since P2P bridges don't differenciate VGA memory and IO | ||
97 | * afaik). You can indicate whether this blocking should be interruptible | ||
98 | * by a signal (for userland interface) or not. | ||
99 | * Must not be called at interrupt time or in atomic context. | ||
100 | * If the card already owns the resources, the function succeeds. | ||
101 | * Nested calls are supported (a per-resource counter is maintained) | ||
102 | */ | ||
103 | |||
104 | #if defined(CONFIG_VGA_ARB) | 76 | #if defined(CONFIG_VGA_ARB) |
105 | extern int vga_get(struct pci_dev *pdev, unsigned int rsrc, int interruptible); | 77 | extern int vga_get(struct pci_dev *pdev, unsigned int rsrc, int interruptible); |
106 | #else | 78 | #else |
@@ -108,11 +80,14 @@ static inline int vga_get(struct pci_dev *pdev, unsigned int rsrc, int interrupt | |||
108 | #endif | 80 | #endif |
109 | 81 | ||
110 | /** | 82 | /** |
111 | * vga_get_interruptible | 83 | * vga_get_interruptible |
84 | * @pdev: pci device of the VGA card or NULL for the system default | ||
85 | * @rsrc: bit mask of resources to acquire and lock | ||
112 | * | 86 | * |
113 | * Shortcut to vga_get | 87 | * Shortcut to vga_get with interruptible set to true. |
88 | * | ||
89 | * On success, release the VGA resource again with vga_put(). | ||
114 | */ | 90 | */ |
115 | |||
116 | static inline int vga_get_interruptible(struct pci_dev *pdev, | 91 | static inline int vga_get_interruptible(struct pci_dev *pdev, |
117 | unsigned int rsrc) | 92 | unsigned int rsrc) |
118 | { | 93 | { |
@@ -120,47 +95,26 @@ static inline int vga_get_interruptible(struct pci_dev *pdev, | |||
120 | } | 95 | } |
121 | 96 | ||
122 | /** | 97 | /** |
123 | * vga_get_uninterruptible | 98 | * vga_get_uninterruptible - shortcut to vga_get() |
99 | * @pdev: pci device of the VGA card or NULL for the system default | ||
100 | * @rsrc: bit mask of resources to acquire and lock | ||
124 | * | 101 | * |
125 | * Shortcut to vga_get | 102 | * Shortcut to vga_get with interruptible set to false. |
103 | * | ||
104 | * On success, release the VGA resource again with vga_put(). | ||
126 | */ | 105 | */ |
127 | |||
128 | static inline int vga_get_uninterruptible(struct pci_dev *pdev, | 106 | static inline int vga_get_uninterruptible(struct pci_dev *pdev, |
129 | unsigned int rsrc) | 107 | unsigned int rsrc) |
130 | { | 108 | { |
131 | return vga_get(pdev, rsrc, 0); | 109 | return vga_get(pdev, rsrc, 0); |
132 | } | 110 | } |
133 | 111 | ||
134 | /** | ||
135 | * vga_tryget - try to acquire & lock legacy VGA resources | ||
136 | * | ||
137 | * @pdev: pci devivce of VGA card or NULL for system default | ||
138 | * @rsrc: bit mask of resources to acquire and lock | ||
139 | * | ||
140 | * This function performs the same operation as vga_get(), but | ||
141 | * will return an error (-EBUSY) instead of blocking if the resources | ||
142 | * are already locked by another card. It can be called in any context | ||
143 | */ | ||
144 | |||
145 | #if defined(CONFIG_VGA_ARB) | 112 | #if defined(CONFIG_VGA_ARB) |
146 | extern int vga_tryget(struct pci_dev *pdev, unsigned int rsrc); | 113 | extern int vga_tryget(struct pci_dev *pdev, unsigned int rsrc); |
147 | #else | 114 | #else |
148 | static inline int vga_tryget(struct pci_dev *pdev, unsigned int rsrc) { return 0; } | 115 | static inline int vga_tryget(struct pci_dev *pdev, unsigned int rsrc) { return 0; } |
149 | #endif | 116 | #endif |
150 | 117 | ||
151 | /** | ||
152 | * vga_put - release lock on legacy VGA resources | ||
153 | * | ||
154 | * @pdev: pci device of VGA card or NULL for system default | ||
155 | * @rsrc: but mask of resource to release | ||
156 | * | ||
157 | * This function releases resources previously locked by vga_get() | ||
158 | * or vga_tryget(). The resources aren't disabled right away, so | ||
159 | * that a subsequence vga_get() on the same card will succeed | ||
160 | * immediately. Resources have a counter, so locks are only | ||
161 | * released if the counter reaches 0. | ||
162 | */ | ||
163 | |||
164 | #if defined(CONFIG_VGA_ARB) | 118 | #if defined(CONFIG_VGA_ARB) |
165 | extern void vga_put(struct pci_dev *pdev, unsigned int rsrc); | 119 | extern void vga_put(struct pci_dev *pdev, unsigned int rsrc); |
166 | #else | 120 | #else |
@@ -168,25 +122,6 @@ extern void vga_put(struct pci_dev *pdev, unsigned int rsrc); | |||
168 | #endif | 122 | #endif |
169 | 123 | ||
170 | 124 | ||
171 | /** | ||
172 | * vga_default_device | ||
173 | * | ||
174 | * This can be defined by the platform. The default implementation | ||
175 | * is rather dumb and will probably only work properly on single | ||
176 | * vga card setups and/or x86 platforms. | ||
177 | * | ||
178 | * If your VGA default device is not PCI, you'll have to return | ||
179 | * NULL here. In this case, I assume it will not conflict with | ||
180 | * any PCI card. If this is not true, I'll have to define two archs | ||
181 | * hooks for enabling/disabling the VGA default device if that is | ||
182 | * possible. This may be a problem with real _ISA_ VGA cards, in | ||
183 | * addition to a PCI one. I don't know at this point how to deal | ||
184 | * with that card. Can theirs IOs be disabled at all ? If not, then | ||
185 | * I suppose it's a matter of having the proper arch hook telling | ||
186 | * us about it, so we basically never allow anybody to succeed a | ||
187 | * vga_get()... | ||
188 | */ | ||
189 | |||
190 | #ifdef CONFIG_VGA_ARB | 125 | #ifdef CONFIG_VGA_ARB |
191 | extern struct pci_dev *vga_default_device(void); | 126 | extern struct pci_dev *vga_default_device(void); |
192 | extern void vga_set_default_device(struct pci_dev *pdev); | 127 | extern void vga_set_default_device(struct pci_dev *pdev); |
@@ -195,14 +130,11 @@ static inline struct pci_dev *vga_default_device(void) { return NULL; }; | |||
195 | static inline void vga_set_default_device(struct pci_dev *pdev) { }; | 130 | static inline void vga_set_default_device(struct pci_dev *pdev) { }; |
196 | #endif | 131 | #endif |
197 | 132 | ||
198 | /** | 133 | /* |
199 | * vga_conflicts | 134 | * Architectures should define this if they have several |
200 | * | 135 | * independent PCI domains that can afford concurrent VGA |
201 | * Architectures should define this if they have several | 136 | * decoding |
202 | * independent PCI domains that can afford concurrent VGA | ||
203 | * decoding | ||
204 | */ | 137 | */ |
205 | |||
206 | #ifndef __ARCH_HAS_VGA_CONFLICT | 138 | #ifndef __ARCH_HAS_VGA_CONFLICT |
207 | static inline int vga_conflicts(struct pci_dev *p1, struct pci_dev *p2) | 139 | static inline int vga_conflicts(struct pci_dev *p1, struct pci_dev *p2) |
208 | { | 140 | { |
@@ -210,34 +142,6 @@ static inline int vga_conflicts(struct pci_dev *p1, struct pci_dev *p2) | |||
210 | } | 142 | } |
211 | #endif | 143 | #endif |
212 | 144 | ||
213 | /** | ||
214 | * vga_client_register | ||
215 | * | ||
216 | * @pdev: pci device of the VGA client | ||
217 | * @cookie: client cookie to be used in callbacks | ||
218 | * @irq_set_state: irq state change callback | ||
219 | * @set_vga_decode: vga decode change callback | ||
220 | * | ||
221 | * return value: 0 on success, -1 on failure | ||
222 | * Register a client with the VGA arbitration logic | ||
223 | * | ||
224 | * Clients have two callback mechanisms they can use. | ||
225 | * irq enable/disable callback - | ||
226 | * If a client can't disable its GPUs VGA resources, then we | ||
227 | * need to be able to ask it to turn off its irqs when we | ||
228 | * turn off its mem and io decoding. | ||
229 | * set_vga_decode | ||
230 | * If a client can disable its GPU VGA resource, it will | ||
231 | * get a callback from this to set the encode/decode state | ||
232 | * | ||
233 | * Rationale: we cannot disable VGA decode resources unconditionally | ||
234 | * some single GPU laptops seem to require ACPI or BIOS access to the | ||
235 | * VGA registers to control things like backlights etc. | ||
236 | * Hopefully newer multi-GPU laptops do something saner, and desktops | ||
237 | * won't have any special ACPI for this. | ||
238 | * They driver will get a callback when VGA arbitration is first used | ||
239 | * by userspace since we some older X servers have issues. | ||
240 | */ | ||
241 | #if defined(CONFIG_VGA_ARB) | 145 | #if defined(CONFIG_VGA_ARB) |
242 | int vga_client_register(struct pci_dev *pdev, void *cookie, | 146 | int vga_client_register(struct pci_dev *pdev, void *cookie, |
243 | void (*irq_set_state)(void *cookie, bool state), | 147 | void (*irq_set_state)(void *cookie, bool state), |