1 | /* |
2 | * vga_switcheroo.c - Support for laptop with dual GPU using one set of outputs |
3 | * |
4 | * Copyright (c) 2010 Red Hat Inc. |
5 | * Author : Dave Airlie <airlied@redhat.com> |
6 | * |
7 | * Copyright (c) 2015 Lukas Wunner <lukas@wunner.de> |
8 | * |
9 | * Permission is hereby granted, free of charge, to any person obtaining a |
10 | * copy of this software and associated documentation files (the "Software"), |
11 | * to deal in the Software without restriction, including without limitation |
12 | * the rights to use, copy, modify, merge, publish, distribute, sublicense, |
13 | * and/or sell copies of the Software, and to permit persons to whom the |
14 | * Software is furnished to do so, subject to the following conditions: |
15 | * |
16 | * The above copyright notice and this permission notice (including the next |
17 | * paragraph) shall be included in all copies or substantial portions of the |
18 | * Software. |
19 | * |
20 | * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR |
21 | * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, |
22 | * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL |
23 | * THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER |
24 | * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING |
25 | * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER |
26 | * DEALINGS |
27 | * IN THE SOFTWARE. |
28 | * |
29 | */ |
30 | |
31 | #define pr_fmt(fmt) "vga_switcheroo: " fmt |
32 | |
33 | #include <linux/apple-gmux.h> |
34 | #include <linux/console.h> |
35 | #include <linux/debugfs.h> |
36 | #include <linux/fb.h> |
37 | #include <linux/fs.h> |
38 | #include <linux/fbcon.h> |
39 | #include <linux/module.h> |
40 | #include <linux/pci.h> |
41 | #include <linux/pm_domain.h> |
42 | #include <linux/pm_runtime.h> |
43 | #include <linux/seq_file.h> |
44 | #include <linux/uaccess.h> |
45 | #include <linux/vgaarb.h> |
46 | #include <linux/vga_switcheroo.h> |
47 | |
48 | /** |
49 | * DOC: Overview |
50 | * |
51 | * vga_switcheroo is the Linux subsystem for laptop hybrid graphics. |
52 | * These come in two flavors: |
53 | * |
54 | * * muxed: Dual GPUs with a multiplexer chip to switch outputs between GPUs. |
55 | * * muxless: Dual GPUs but only one of them is connected to outputs. |
56 | * The other one is merely used to offload rendering, its results |
57 | * are copied over PCIe into the framebuffer. On Linux this is |
58 | * supported with DRI PRIME. |
59 | * |
60 | * Hybrid graphics started to appear in the late Naughties and were initially |
61 | * all muxed. Newer laptops moved to a muxless architecture for cost reasons. |
62 | * A notable exception is the MacBook Pro which continues to use a mux. |
63 | * Muxes come with varying capabilities: Some switch only the panel, others |
64 | * can also switch external displays. Some switch all display pins at once |
65 | * while others can switch just the DDC lines. (To allow EDID probing |
66 | * for the inactive GPU.) Also, muxes are often used to cut power to the |
67 | * discrete GPU while it is not used. |
68 | * |
69 | * DRM drivers register GPUs with vga_switcheroo, these are henceforth called |
70 | * clients. The mux is called the handler. Muxless machines also register a |
71 | * handler to control the power state of the discrete GPU, its ->switchto |
72 | * callback is a no-op for obvious reasons. The discrete GPU is often equipped |
73 | * with an HDA controller for the HDMI/DP audio signal, this will also |
74 | * register as a client so that vga_switcheroo can take care of the correct |
75 | * suspend/resume order when changing the discrete GPU's power state. In total |
76 | * there can thus be up to three clients: Two vga clients (GPUs) and one audio |
77 | * client (on the discrete GPU). The code is mostly prepared to support |
78 | * machines with more than two GPUs should they become available. |
79 | * |
80 | * The GPU to which the outputs are currently switched is called the |
81 | * active client in vga_switcheroo parlance. The GPU not in use is the |
82 | * inactive client. When the inactive client's DRM driver is loaded, |
83 | * it will be unable to probe the panel's EDID and hence depends on |
84 | * VBIOS to provide its display modes. If the VBIOS modes are bogus or |
85 | * if there is no VBIOS at all (which is common on the MacBook Pro), |
86 | * a client may alternatively request that the DDC lines are temporarily |
87 | * switched to it, provided that the handler supports this. Switching |
88 | * only the DDC lines and not the entire output avoids unnecessary |
89 | * flickering. |
90 | */ |
91 | |
92 | /** |
93 | * struct vga_switcheroo_client - registered client |
94 | * @pdev: client pci device |
95 | * @fb_info: framebuffer to which console is remapped on switching |
96 | * @pwr_state: current power state if manual power control is used. |
97 | * For driver power control, call vga_switcheroo_pwr_state(). |
98 | * @ops: client callbacks |
99 | * @id: client identifier. Determining the id requires the handler, |
100 | * so gpus are initially assigned VGA_SWITCHEROO_UNKNOWN_ID |
101 | * and later given their true id in vga_switcheroo_enable() |
102 | * @active: whether the outputs are currently switched to this client |
103 | * @driver_power_control: whether power state is controlled by the driver's |
104 | * runtime pm. If true, writing ON and OFF to the vga_switcheroo debugfs |
105 | * interface is a no-op so as not to interfere with runtime pm |
106 | * @list: client list |
107 | * @vga_dev: pci device, indicate which GPU is bound to current audio client |
108 | * |
109 | * Registered client. A client can be either a GPU or an audio device on a GPU. |
110 | * For audio clients, the @fb_info and @active members are bogus. For GPU |
111 | * clients, the @vga_dev is bogus. |
112 | */ |
113 | struct vga_switcheroo_client { |
114 | struct pci_dev *pdev; |
115 | struct fb_info *fb_info; |
116 | enum vga_switcheroo_state pwr_state; |
117 | const struct vga_switcheroo_client_ops *ops; |
118 | enum vga_switcheroo_client_id id; |
119 | bool active; |
120 | bool driver_power_control; |
121 | struct list_head list; |
122 | struct pci_dev *vga_dev; |
123 | }; |
124 | |
125 | /* |
126 | * protects access to struct vgasr_priv |
127 | */ |
128 | static DEFINE_MUTEX(vgasr_mutex); |
129 | |
130 | /** |
131 | * struct vgasr_priv - vga_switcheroo private data |
132 | * @active: whether vga_switcheroo is enabled. |
133 | * Prerequisite is the registration of two GPUs and a handler |
134 | * @delayed_switch_active: whether a delayed switch is pending |
135 | * @delayed_client_id: client to which a delayed switch is pending |
136 | * @debugfs_root: directory for vga_switcheroo debugfs interface |
137 | * @registered_clients: number of registered GPUs |
138 | * (counting only vga clients, not audio clients) |
139 | * @clients: list of registered clients |
140 | * @handler: registered handler |
141 | * @handler_flags: flags of registered handler |
142 | * @mux_hw_lock: protects mux state |
143 | * (in particular while DDC lines are temporarily switched) |
144 | * @old_ddc_owner: client to which DDC lines will be switched back on unlock |
145 | * |
146 | * vga_switcheroo private data. Currently only one vga_switcheroo instance |
147 | * per system is supported. |
148 | */ |
149 | struct vgasr_priv { |
150 | bool active; |
151 | bool delayed_switch_active; |
152 | enum vga_switcheroo_client_id delayed_client_id; |
153 | |
154 | struct dentry *debugfs_root; |
155 | |
156 | int registered_clients; |
157 | struct list_head clients; |
158 | |
159 | const struct vga_switcheroo_handler *handler; |
160 | enum vga_switcheroo_handler_flags_t handler_flags; |
161 | struct mutex mux_hw_lock; |
162 | int old_ddc_owner; |
163 | }; |
164 | |
165 | #define ID_BIT_AUDIO 0x100 |
166 | #define client_is_audio(c) ((c)->id & ID_BIT_AUDIO) |
167 | #define client_is_vga(c) (!client_is_audio(c)) |
168 | #define client_id(c) ((c)->id & ~ID_BIT_AUDIO) |
169 | |
170 | static void vga_switcheroo_debugfs_init(struct vgasr_priv *priv); |
171 | static void vga_switcheroo_debugfs_fini(struct vgasr_priv *priv); |
172 | |
173 | /* only one switcheroo per system */ |
174 | static struct vgasr_priv vgasr_priv = { |
175 | .clients = LIST_HEAD_INIT(vgasr_priv.clients), |
176 | .mux_hw_lock = __MUTEX_INITIALIZER(vgasr_priv.mux_hw_lock), |
177 | }; |
178 | |
179 | static bool vga_switcheroo_ready(void) |
180 | { |
181 | /* we're ready if we get two clients + handler */ |
182 | return !vgasr_priv.active && |
183 | vgasr_priv.registered_clients == 2 && vgasr_priv.handler; |
184 | } |
185 | |
186 | static void vga_switcheroo_enable(void) |
187 | { |
188 | int ret; |
189 | struct vga_switcheroo_client *client; |
190 | |
191 | /* call the handler to init */ |
192 | if (vgasr_priv.handler->init) |
193 | vgasr_priv.handler->init(); |
194 | |
195 | list_for_each_entry(client, &vgasr_priv.clients, list) { |
196 | if (!client_is_vga(client) || |
197 | client_id(client) != VGA_SWITCHEROO_UNKNOWN_ID) |
198 | continue; |
199 | |
200 | ret = vgasr_priv.handler->get_client_id(client->pdev); |
201 | if (ret < 0) |
202 | return; |
203 | |
204 | client->id = ret; |
205 | } |
206 | |
207 | list_for_each_entry(client, &vgasr_priv.clients, list) { |
208 | if (!client_is_audio(client) || |
209 | client_id(client) != VGA_SWITCHEROO_UNKNOWN_ID) |
210 | continue; |
211 | |
212 | ret = vgasr_priv.handler->get_client_id(client->vga_dev); |
213 | if (ret < 0) |
214 | return; |
215 | |
216 | client->id = ret | ID_BIT_AUDIO; |
217 | if (client->ops->gpu_bound) |
218 | client->ops->gpu_bound(client->pdev, ret); |
219 | } |
220 | |
221 | vga_switcheroo_debugfs_init(priv: &vgasr_priv); |
222 | vgasr_priv.active = true; |
223 | } |
224 | |
225 | /** |
226 | * vga_switcheroo_register_handler() - register handler |
227 | * @handler: handler callbacks |
228 | * @handler_flags: handler flags |
229 | * |
230 | * Register handler. Enable vga_switcheroo if two vga clients have already |
231 | * registered. |
232 | * |
233 | * Return: 0 on success, -EINVAL if a handler was already registered. |
234 | */ |
235 | int vga_switcheroo_register_handler( |
236 | const struct vga_switcheroo_handler *handler, |
237 | enum vga_switcheroo_handler_flags_t handler_flags) |
238 | { |
239 | mutex_lock(&vgasr_mutex); |
240 | if (vgasr_priv.handler) { |
241 | mutex_unlock(lock: &vgasr_mutex); |
242 | return -EINVAL; |
243 | } |
244 | |
245 | vgasr_priv.handler = handler; |
246 | vgasr_priv.handler_flags = handler_flags; |
247 | if (vga_switcheroo_ready()) { |
248 | pr_info("enabled\n" ); |
249 | vga_switcheroo_enable(); |
250 | } |
251 | mutex_unlock(lock: &vgasr_mutex); |
252 | return 0; |
253 | } |
254 | EXPORT_SYMBOL(vga_switcheroo_register_handler); |
255 | |
256 | /** |
257 | * vga_switcheroo_unregister_handler() - unregister handler |
258 | * |
259 | * Unregister handler. Disable vga_switcheroo. |
260 | */ |
261 | void vga_switcheroo_unregister_handler(void) |
262 | { |
263 | mutex_lock(&vgasr_mutex); |
264 | mutex_lock(&vgasr_priv.mux_hw_lock); |
265 | vgasr_priv.handler_flags = 0; |
266 | vgasr_priv.handler = NULL; |
267 | if (vgasr_priv.active) { |
268 | pr_info("disabled\n" ); |
269 | vga_switcheroo_debugfs_fini(priv: &vgasr_priv); |
270 | vgasr_priv.active = false; |
271 | } |
272 | mutex_unlock(lock: &vgasr_priv.mux_hw_lock); |
273 | mutex_unlock(lock: &vgasr_mutex); |
274 | } |
275 | EXPORT_SYMBOL(vga_switcheroo_unregister_handler); |
276 | |
277 | /** |
278 | * vga_switcheroo_handler_flags() - obtain handler flags |
279 | * |
280 | * Helper for clients to obtain the handler flags bitmask. |
281 | * |
282 | * Return: Handler flags. A value of 0 means that no handler is registered |
283 | * or that the handler has no special capabilities. |
284 | */ |
285 | enum vga_switcheroo_handler_flags_t vga_switcheroo_handler_flags(void) |
286 | { |
287 | return vgasr_priv.handler_flags; |
288 | } |
289 | EXPORT_SYMBOL(vga_switcheroo_handler_flags); |
290 | |
291 | static int register_client(struct pci_dev *pdev, |
292 | const struct vga_switcheroo_client_ops *ops, |
293 | enum vga_switcheroo_client_id id, |
294 | struct pci_dev *vga_dev, |
295 | bool active, |
296 | bool driver_power_control) |
297 | { |
298 | struct vga_switcheroo_client *client; |
299 | |
300 | client = kzalloc(size: sizeof(*client), GFP_KERNEL); |
301 | if (!client) |
302 | return -ENOMEM; |
303 | |
304 | client->pwr_state = VGA_SWITCHEROO_ON; |
305 | client->pdev = pdev; |
306 | client->ops = ops; |
307 | client->id = id; |
308 | client->active = active; |
309 | client->driver_power_control = driver_power_control; |
310 | client->vga_dev = vga_dev; |
311 | |
312 | mutex_lock(&vgasr_mutex); |
313 | list_add_tail(new: &client->list, head: &vgasr_priv.clients); |
314 | if (client_is_vga(client)) |
315 | vgasr_priv.registered_clients++; |
316 | |
317 | if (vga_switcheroo_ready()) { |
318 | pr_info("enabled\n" ); |
319 | vga_switcheroo_enable(); |
320 | } |
321 | mutex_unlock(lock: &vgasr_mutex); |
322 | return 0; |
323 | } |
324 | |
325 | /** |
326 | * vga_switcheroo_register_client - register vga client |
327 | * @pdev: client pci device |
328 | * @ops: client callbacks |
329 | * @driver_power_control: whether power state is controlled by the driver's |
330 | * runtime pm |
331 | * |
332 | * Register vga client (GPU). Enable vga_switcheroo if another GPU and a |
333 | * handler have already registered. The power state of the client is assumed |
334 | * to be ON. Beforehand, vga_switcheroo_client_probe_defer() shall be called |
335 | * to ensure that all prerequisites are met. |
336 | * |
337 | * Return: 0 on success, -ENOMEM on memory allocation error. |
338 | */ |
339 | int vga_switcheroo_register_client(struct pci_dev *pdev, |
340 | const struct vga_switcheroo_client_ops *ops, |
341 | bool driver_power_control) |
342 | { |
343 | return register_client(pdev, ops, id: VGA_SWITCHEROO_UNKNOWN_ID, NULL, |
344 | active: pdev == vga_default_device(), |
345 | driver_power_control); |
346 | } |
347 | EXPORT_SYMBOL(vga_switcheroo_register_client); |
348 | |
349 | /** |
350 | * vga_switcheroo_register_audio_client - register audio client |
351 | * @pdev: client pci device |
352 | * @ops: client callbacks |
353 | * @vga_dev: pci device which is bound to current audio client |
354 | * |
355 | * Register audio client (audio device on a GPU). The client is assumed |
356 | * to use runtime PM. Beforehand, vga_switcheroo_client_probe_defer() |
357 | * shall be called to ensure that all prerequisites are met. |
358 | * |
359 | * Return: 0 on success, -ENOMEM on memory allocation error, -EINVAL on getting |
360 | * client id error. |
361 | */ |
362 | int vga_switcheroo_register_audio_client(struct pci_dev *pdev, |
363 | const struct vga_switcheroo_client_ops *ops, |
364 | struct pci_dev *vga_dev) |
365 | { |
366 | enum vga_switcheroo_client_id id = VGA_SWITCHEROO_UNKNOWN_ID; |
367 | |
368 | /* |
369 | * if vga_switcheroo has enabled, that mean two GPU clients and also |
370 | * handler are registered. Get audio client id from bound GPU client |
371 | * id directly, otherwise, set it as VGA_SWITCHEROO_UNKNOWN_ID, |
372 | * it will set to correct id in later when vga_switcheroo_enable() |
373 | * is called. |
374 | */ |
375 | mutex_lock(&vgasr_mutex); |
376 | if (vgasr_priv.active) { |
377 | id = vgasr_priv.handler->get_client_id(vga_dev); |
378 | if (id < 0) { |
379 | mutex_unlock(lock: &vgasr_mutex); |
380 | return -EINVAL; |
381 | } |
382 | /* notify if GPU has been already bound */ |
383 | if (ops->gpu_bound) |
384 | ops->gpu_bound(pdev, id); |
385 | } |
386 | mutex_unlock(lock: &vgasr_mutex); |
387 | |
388 | return register_client(pdev, ops, id: id | ID_BIT_AUDIO, vga_dev, |
389 | active: false, driver_power_control: true); |
390 | } |
391 | EXPORT_SYMBOL(vga_switcheroo_register_audio_client); |
392 | |
393 | static struct vga_switcheroo_client * |
394 | find_client_from_pci(struct list_head *head, struct pci_dev *pdev) |
395 | { |
396 | struct vga_switcheroo_client *client; |
397 | |
398 | list_for_each_entry(client, head, list) |
399 | if (client->pdev == pdev) |
400 | return client; |
401 | return NULL; |
402 | } |
403 | |
404 | static struct vga_switcheroo_client * |
405 | find_client_from_id(struct list_head *head, |
406 | enum vga_switcheroo_client_id client_id) |
407 | { |
408 | struct vga_switcheroo_client *client; |
409 | |
410 | list_for_each_entry(client, head, list) |
411 | if (client->id == client_id) |
412 | return client; |
413 | return NULL; |
414 | } |
415 | |
416 | static struct vga_switcheroo_client * |
417 | find_active_client(struct list_head *head) |
418 | { |
419 | struct vga_switcheroo_client *client; |
420 | |
421 | list_for_each_entry(client, head, list) |
422 | if (client->active) |
423 | return client; |
424 | return NULL; |
425 | } |
426 | |
427 | /** |
428 | * vga_switcheroo_client_probe_defer() - whether to defer probing a given client |
429 | * @pdev: client pci device |
430 | * |
431 | * Determine whether any prerequisites are not fulfilled to probe a given |
432 | * client. Drivers shall invoke this early on in their ->probe callback |
433 | * and return %-EPROBE_DEFER if it evaluates to %true. Thou shalt not |
434 | * register the client ere thou hast called this. |
435 | * |
436 | * Return: %true if probing should be deferred, otherwise %false. |
437 | */ |
438 | bool vga_switcheroo_client_probe_defer(struct pci_dev *pdev) |
439 | { |
440 | if ((pdev->class >> 16) == PCI_BASE_CLASS_DISPLAY) { |
441 | /* |
442 | * apple-gmux is needed on pre-retina MacBook Pro |
443 | * to probe the panel if pdev is the inactive GPU. |
444 | */ |
445 | if (apple_gmux_present() && pdev != vga_default_device() && |
446 | !vgasr_priv.handler_flags) |
447 | return true; |
448 | } |
449 | |
450 | return false; |
451 | } |
452 | EXPORT_SYMBOL(vga_switcheroo_client_probe_defer); |
453 | |
454 | static enum vga_switcheroo_state |
455 | vga_switcheroo_pwr_state(struct vga_switcheroo_client *client) |
456 | { |
457 | if (client->driver_power_control) |
458 | if (pm_runtime_enabled(dev: &client->pdev->dev) && |
459 | pm_runtime_active(dev: &client->pdev->dev)) |
460 | return VGA_SWITCHEROO_ON; |
461 | else |
462 | return VGA_SWITCHEROO_OFF; |
463 | else |
464 | return client->pwr_state; |
465 | } |
466 | |
467 | /** |
468 | * vga_switcheroo_get_client_state() - obtain power state of a given client |
469 | * @pdev: client pci device |
470 | * |
471 | * Obtain power state of a given client as seen from vga_switcheroo. |
472 | * The function is only called from hda_intel.c. |
473 | * |
474 | * Return: Power state. |
475 | */ |
476 | enum vga_switcheroo_state vga_switcheroo_get_client_state(struct pci_dev *pdev) |
477 | { |
478 | struct vga_switcheroo_client *client; |
479 | enum vga_switcheroo_state ret; |
480 | |
481 | mutex_lock(&vgasr_mutex); |
482 | client = find_client_from_pci(head: &vgasr_priv.clients, pdev); |
483 | if (!client) |
484 | ret = VGA_SWITCHEROO_NOT_FOUND; |
485 | else |
486 | ret = vga_switcheroo_pwr_state(client); |
487 | mutex_unlock(lock: &vgasr_mutex); |
488 | return ret; |
489 | } |
490 | EXPORT_SYMBOL(vga_switcheroo_get_client_state); |
491 | |
492 | /** |
493 | * vga_switcheroo_unregister_client() - unregister client |
494 | * @pdev: client pci device |
495 | * |
496 | * Unregister client. Disable vga_switcheroo if this is a vga client (GPU). |
497 | */ |
498 | void vga_switcheroo_unregister_client(struct pci_dev *pdev) |
499 | { |
500 | struct vga_switcheroo_client *client; |
501 | |
502 | mutex_lock(&vgasr_mutex); |
503 | client = find_client_from_pci(head: &vgasr_priv.clients, pdev); |
504 | if (client) { |
505 | if (client_is_vga(client)) |
506 | vgasr_priv.registered_clients--; |
507 | list_del(entry: &client->list); |
508 | kfree(objp: client); |
509 | } |
510 | if (vgasr_priv.active && vgasr_priv.registered_clients < 2) { |
511 | pr_info("disabled\n" ); |
512 | vga_switcheroo_debugfs_fini(priv: &vgasr_priv); |
513 | vgasr_priv.active = false; |
514 | } |
515 | mutex_unlock(lock: &vgasr_mutex); |
516 | } |
517 | EXPORT_SYMBOL(vga_switcheroo_unregister_client); |
518 | |
519 | /** |
520 | * vga_switcheroo_client_fb_set() - set framebuffer of a given client |
521 | * @pdev: client pci device |
522 | * @info: framebuffer |
523 | * |
524 | * Set framebuffer of a given client. The console will be remapped to this |
525 | * on switching. |
526 | */ |
527 | void vga_switcheroo_client_fb_set(struct pci_dev *pdev, |
528 | struct fb_info *info) |
529 | { |
530 | struct vga_switcheroo_client *client; |
531 | |
532 | mutex_lock(&vgasr_mutex); |
533 | client = find_client_from_pci(head: &vgasr_priv.clients, pdev); |
534 | if (client) |
535 | client->fb_info = info; |
536 | mutex_unlock(lock: &vgasr_mutex); |
537 | } |
538 | EXPORT_SYMBOL(vga_switcheroo_client_fb_set); |
539 | |
540 | /** |
541 | * vga_switcheroo_lock_ddc() - temporarily switch DDC lines to a given client |
542 | * @pdev: client pci device |
543 | * |
544 | * Temporarily switch DDC lines to the client identified by @pdev |
545 | * (but leave the outputs otherwise switched to where they are). |
546 | * This allows the inactive client to probe EDID. The DDC lines must |
547 | * afterwards be switched back by calling vga_switcheroo_unlock_ddc(), |
548 | * even if this function returns an error. |
549 | * |
550 | * Return: Previous DDC owner on success or a negative int on error. |
551 | * Specifically, %-ENODEV if no handler has registered or if the handler |
552 | * does not support switching the DDC lines. Also, a negative value |
553 | * returned by the handler is propagated back to the caller. |
554 | * The return value has merely an informational purpose for any caller |
555 | * which might be interested in it. It is acceptable to ignore the return |
556 | * value and simply rely on the result of the subsequent EDID probe, |
557 | * which will be %NULL if DDC switching failed. |
558 | */ |
559 | int vga_switcheroo_lock_ddc(struct pci_dev *pdev) |
560 | { |
561 | enum vga_switcheroo_client_id id; |
562 | |
563 | mutex_lock(&vgasr_priv.mux_hw_lock); |
564 | if (!vgasr_priv.handler || !vgasr_priv.handler->switch_ddc) { |
565 | vgasr_priv.old_ddc_owner = -ENODEV; |
566 | return -ENODEV; |
567 | } |
568 | |
569 | id = vgasr_priv.handler->get_client_id(pdev); |
570 | vgasr_priv.old_ddc_owner = vgasr_priv.handler->switch_ddc(id); |
571 | return vgasr_priv.old_ddc_owner; |
572 | } |
573 | EXPORT_SYMBOL(vga_switcheroo_lock_ddc); |
574 | |
575 | /** |
576 | * vga_switcheroo_unlock_ddc() - switch DDC lines back to previous owner |
577 | * @pdev: client pci device |
578 | * |
579 | * Switch DDC lines back to the previous owner after calling |
580 | * vga_switcheroo_lock_ddc(). This must be called even if |
581 | * vga_switcheroo_lock_ddc() returned an error. |
582 | * |
583 | * Return: Previous DDC owner on success (i.e. the client identifier of @pdev) |
584 | * or a negative int on error. |
585 | * Specifically, %-ENODEV if no handler has registered or if the handler |
586 | * does not support switching the DDC lines. Also, a negative value |
587 | * returned by the handler is propagated back to the caller. |
588 | * Finally, invoking this function without calling vga_switcheroo_lock_ddc() |
589 | * first is not allowed and will result in %-EINVAL. |
590 | */ |
591 | int vga_switcheroo_unlock_ddc(struct pci_dev *pdev) |
592 | { |
593 | enum vga_switcheroo_client_id id; |
594 | int ret = vgasr_priv.old_ddc_owner; |
595 | |
596 | if (WARN_ON_ONCE(!mutex_is_locked(&vgasr_priv.mux_hw_lock))) |
597 | return -EINVAL; |
598 | |
599 | if (vgasr_priv.old_ddc_owner >= 0) { |
600 | id = vgasr_priv.handler->get_client_id(pdev); |
601 | if (vgasr_priv.old_ddc_owner != id) |
602 | ret = vgasr_priv.handler->switch_ddc( |
603 | vgasr_priv.old_ddc_owner); |
604 | } |
605 | mutex_unlock(lock: &vgasr_priv.mux_hw_lock); |
606 | return ret; |
607 | } |
608 | EXPORT_SYMBOL(vga_switcheroo_unlock_ddc); |
609 | |
610 | /** |
611 | * DOC: Manual switching and manual power control |
612 | * |
613 | * In this mode of use, the file /sys/kernel/debug/vgaswitcheroo/switch |
614 | * can be read to retrieve the current vga_switcheroo state and commands |
615 | * can be written to it to change the state. The file appears as soon as |
616 | * two GPU drivers and one handler have registered with vga_switcheroo. |
617 | * The following commands are understood: |
618 | * |
619 | * * OFF: Power off the device not in use. |
620 | * * ON: Power on the device not in use. |
621 | * * IGD: Switch to the integrated graphics device. |
622 | * Power on the integrated GPU if necessary, power off the discrete GPU. |
623 | * Prerequisite is that no user space processes (e.g. Xorg, alsactl) |
624 | * have opened device files of the GPUs or the audio client. If the |
625 | * switch fails, the user may invoke lsof(8) or fuser(1) on /dev/dri/ |
626 | * and /dev/snd/controlC1 to identify processes blocking the switch. |
627 | * * DIS: Switch to the discrete graphics device. |
628 | * * DIGD: Delayed switch to the integrated graphics device. |
629 | * This will perform the switch once the last user space process has |
630 | * closed the device files of the GPUs and the audio client. |
631 | * * DDIS: Delayed switch to the discrete graphics device. |
632 | * * MIGD: Mux-only switch to the integrated graphics device. |
633 | * Does not remap console or change the power state of either gpu. |
634 | * If the integrated GPU is currently off, the screen will turn black. |
635 | * If it is on, the screen will show whatever happens to be in VRAM. |
636 | * Either way, the user has to blindly enter the command to switch back. |
637 | * * MDIS: Mux-only switch to the discrete graphics device. |
638 | * |
639 | * For GPUs whose power state is controlled by the driver's runtime pm, |
640 | * the ON and OFF commands are a no-op (see next section). |
641 | * |
642 | * For muxless machines, the IGD/DIS, DIGD/DDIS and MIGD/MDIS commands |
643 | * should not be used. |
644 | */ |
645 | |
646 | static int vga_switcheroo_show(struct seq_file *m, void *v) |
647 | { |
648 | struct vga_switcheroo_client *client; |
649 | int i = 0; |
650 | |
651 | mutex_lock(&vgasr_mutex); |
652 | list_for_each_entry(client, &vgasr_priv.clients, list) { |
653 | seq_printf(m, fmt: "%d:%s%s:%c:%s%s:%s\n" , i, |
654 | client_id(client) == VGA_SWITCHEROO_DIS ? "DIS" : |
655 | "IGD" , |
656 | client_is_vga(client) ? "" : "-Audio" , |
657 | client->active ? '+' : ' ', |
658 | client->driver_power_control ? "Dyn" : "" , |
659 | vga_switcheroo_pwr_state(client) ? "Pwr" : "Off" , |
660 | pci_name(pdev: client->pdev)); |
661 | i++; |
662 | } |
663 | mutex_unlock(lock: &vgasr_mutex); |
664 | return 0; |
665 | } |
666 | |
667 | static int vga_switcheroo_debugfs_open(struct inode *inode, struct file *file) |
668 | { |
669 | return single_open(file, vga_switcheroo_show, NULL); |
670 | } |
671 | |
672 | static int vga_switchon(struct vga_switcheroo_client *client) |
673 | { |
674 | if (client->driver_power_control) |
675 | return 0; |
676 | if (vgasr_priv.handler->power_state) |
677 | vgasr_priv.handler->power_state(client->id, VGA_SWITCHEROO_ON); |
678 | /* call the driver callback to turn on device */ |
679 | client->ops->set_gpu_state(client->pdev, VGA_SWITCHEROO_ON); |
680 | client->pwr_state = VGA_SWITCHEROO_ON; |
681 | return 0; |
682 | } |
683 | |
684 | static int vga_switchoff(struct vga_switcheroo_client *client) |
685 | { |
686 | if (client->driver_power_control) |
687 | return 0; |
688 | /* call the driver callback to turn off device */ |
689 | client->ops->set_gpu_state(client->pdev, VGA_SWITCHEROO_OFF); |
690 | if (vgasr_priv.handler->power_state) |
691 | vgasr_priv.handler->power_state(client->id, VGA_SWITCHEROO_OFF); |
692 | client->pwr_state = VGA_SWITCHEROO_OFF; |
693 | return 0; |
694 | } |
695 | |
696 | static void set_audio_state(enum vga_switcheroo_client_id id, |
697 | enum vga_switcheroo_state state) |
698 | { |
699 | struct vga_switcheroo_client *client; |
700 | |
701 | client = find_client_from_id(head: &vgasr_priv.clients, client_id: id | ID_BIT_AUDIO); |
702 | if (client) |
703 | client->ops->set_gpu_state(client->pdev, state); |
704 | } |
705 | |
706 | /* stage one happens before delay */ |
707 | static int vga_switchto_stage1(struct vga_switcheroo_client *new_client) |
708 | { |
709 | struct vga_switcheroo_client *active; |
710 | |
711 | active = find_active_client(head: &vgasr_priv.clients); |
712 | if (!active) |
713 | return 0; |
714 | |
715 | if (vga_switcheroo_pwr_state(client: new_client) == VGA_SWITCHEROO_OFF) |
716 | vga_switchon(client: new_client); |
717 | |
718 | vga_set_default_device(pdev: new_client->pdev); |
719 | return 0; |
720 | } |
721 | |
722 | /* post delay */ |
723 | static int vga_switchto_stage2(struct vga_switcheroo_client *new_client) |
724 | { |
725 | int ret; |
726 | struct vga_switcheroo_client *active; |
727 | |
728 | active = find_active_client(head: &vgasr_priv.clients); |
729 | if (!active) |
730 | return 0; |
731 | |
732 | active->active = false; |
733 | |
734 | /* let HDA controller autosuspend if GPU uses driver power control */ |
735 | if (!active->driver_power_control) |
736 | set_audio_state(id: active->id, state: VGA_SWITCHEROO_OFF); |
737 | |
738 | if (new_client->fb_info) |
739 | fbcon_remap_all(info: new_client->fb_info); |
740 | |
741 | mutex_lock(&vgasr_priv.mux_hw_lock); |
742 | ret = vgasr_priv.handler->switchto(new_client->id); |
743 | mutex_unlock(lock: &vgasr_priv.mux_hw_lock); |
744 | if (ret) |
745 | return ret; |
746 | |
747 | if (new_client->ops->reprobe) |
748 | new_client->ops->reprobe(new_client->pdev); |
749 | |
750 | if (vga_switcheroo_pwr_state(client: active) == VGA_SWITCHEROO_ON) |
751 | vga_switchoff(client: active); |
752 | |
753 | /* let HDA controller autoresume if GPU uses driver power control */ |
754 | if (!new_client->driver_power_control) |
755 | set_audio_state(id: new_client->id, state: VGA_SWITCHEROO_ON); |
756 | |
757 | new_client->active = true; |
758 | return 0; |
759 | } |
760 | |
761 | static bool check_can_switch(void) |
762 | { |
763 | struct vga_switcheroo_client *client; |
764 | |
765 | list_for_each_entry(client, &vgasr_priv.clients, list) { |
766 | if (!client->ops->can_switch(client->pdev)) { |
767 | pr_err("client %x refused switch\n" , client->id); |
768 | return false; |
769 | } |
770 | } |
771 | return true; |
772 | } |
773 | |
774 | static ssize_t |
775 | vga_switcheroo_debugfs_write(struct file *filp, const char __user *ubuf, |
776 | size_t cnt, loff_t *ppos) |
777 | { |
778 | char usercmd[64]; |
779 | int ret; |
780 | bool delay = false, can_switch; |
781 | bool just_mux = false; |
782 | enum vga_switcheroo_client_id client_id = VGA_SWITCHEROO_UNKNOWN_ID; |
783 | struct vga_switcheroo_client *client = NULL; |
784 | |
785 | if (cnt > 63) |
786 | cnt = 63; |
787 | |
788 | if (copy_from_user(to: usercmd, from: ubuf, n: cnt)) |
789 | return -EFAULT; |
790 | |
791 | mutex_lock(&vgasr_mutex); |
792 | |
793 | if (!vgasr_priv.active) { |
794 | cnt = -EINVAL; |
795 | goto out; |
796 | } |
797 | |
798 | /* pwr off the device not in use */ |
799 | if (strncmp(usercmd, "OFF" , 3) == 0) { |
800 | list_for_each_entry(client, &vgasr_priv.clients, list) { |
801 | if (client->active || client_is_audio(client)) |
802 | continue; |
803 | if (client->driver_power_control) |
804 | continue; |
805 | set_audio_state(id: client->id, state: VGA_SWITCHEROO_OFF); |
806 | if (client->pwr_state == VGA_SWITCHEROO_ON) |
807 | vga_switchoff(client); |
808 | } |
809 | goto out; |
810 | } |
811 | /* pwr on the device not in use */ |
812 | if (strncmp(usercmd, "ON" , 2) == 0) { |
813 | list_for_each_entry(client, &vgasr_priv.clients, list) { |
814 | if (client->active || client_is_audio(client)) |
815 | continue; |
816 | if (client->driver_power_control) |
817 | continue; |
818 | if (client->pwr_state == VGA_SWITCHEROO_OFF) |
819 | vga_switchon(client); |
820 | set_audio_state(id: client->id, state: VGA_SWITCHEROO_ON); |
821 | } |
822 | goto out; |
823 | } |
824 | |
825 | /* request a delayed switch - test can we switch now */ |
826 | if (strncmp(usercmd, "DIGD" , 4) == 0) { |
827 | client_id = VGA_SWITCHEROO_IGD; |
828 | delay = true; |
829 | } |
830 | |
831 | if (strncmp(usercmd, "DDIS" , 4) == 0) { |
832 | client_id = VGA_SWITCHEROO_DIS; |
833 | delay = true; |
834 | } |
835 | |
836 | if (strncmp(usercmd, "IGD" , 3) == 0) |
837 | client_id = VGA_SWITCHEROO_IGD; |
838 | |
839 | if (strncmp(usercmd, "DIS" , 3) == 0) |
840 | client_id = VGA_SWITCHEROO_DIS; |
841 | |
842 | if (strncmp(usercmd, "MIGD" , 4) == 0) { |
843 | just_mux = true; |
844 | client_id = VGA_SWITCHEROO_IGD; |
845 | } |
846 | if (strncmp(usercmd, "MDIS" , 4) == 0) { |
847 | just_mux = true; |
848 | client_id = VGA_SWITCHEROO_DIS; |
849 | } |
850 | |
851 | if (client_id == VGA_SWITCHEROO_UNKNOWN_ID) |
852 | goto out; |
853 | client = find_client_from_id(head: &vgasr_priv.clients, client_id); |
854 | if (!client) |
855 | goto out; |
856 | |
857 | vgasr_priv.delayed_switch_active = false; |
858 | |
859 | if (just_mux) { |
860 | mutex_lock(&vgasr_priv.mux_hw_lock); |
861 | ret = vgasr_priv.handler->switchto(client_id); |
862 | mutex_unlock(lock: &vgasr_priv.mux_hw_lock); |
863 | goto out; |
864 | } |
865 | |
866 | if (client->active) |
867 | goto out; |
868 | |
869 | /* okay we want a switch - test if devices are willing to switch */ |
870 | can_switch = check_can_switch(); |
871 | |
872 | if (can_switch == false && delay == false) |
873 | goto out; |
874 | |
875 | if (can_switch) { |
876 | ret = vga_switchto_stage1(new_client: client); |
877 | if (ret) |
878 | pr_err("switching failed stage 1 %d\n" , ret); |
879 | |
880 | ret = vga_switchto_stage2(new_client: client); |
881 | if (ret) |
882 | pr_err("switching failed stage 2 %d\n" , ret); |
883 | |
884 | } else { |
885 | pr_info("setting delayed switch to client %d\n" , client->id); |
886 | vgasr_priv.delayed_switch_active = true; |
887 | vgasr_priv.delayed_client_id = client_id; |
888 | |
889 | ret = vga_switchto_stage1(new_client: client); |
890 | if (ret) |
891 | pr_err("delayed switching stage 1 failed %d\n" , ret); |
892 | } |
893 | |
894 | out: |
895 | mutex_unlock(lock: &vgasr_mutex); |
896 | return cnt; |
897 | } |
898 | |
899 | static const struct file_operations vga_switcheroo_debugfs_fops = { |
900 | .owner = THIS_MODULE, |
901 | .open = vga_switcheroo_debugfs_open, |
902 | .write = vga_switcheroo_debugfs_write, |
903 | .read = seq_read, |
904 | .llseek = seq_lseek, |
905 | .release = single_release, |
906 | }; |
907 | |
908 | static void vga_switcheroo_debugfs_fini(struct vgasr_priv *priv) |
909 | { |
910 | debugfs_remove_recursive(dentry: priv->debugfs_root); |
911 | priv->debugfs_root = NULL; |
912 | } |
913 | |
914 | static void vga_switcheroo_debugfs_init(struct vgasr_priv *priv) |
915 | { |
916 | /* already initialised */ |
917 | if (priv->debugfs_root) |
918 | return; |
919 | |
920 | priv->debugfs_root = debugfs_create_dir(name: "vgaswitcheroo" , NULL); |
921 | |
922 | debugfs_create_file(name: "switch" , mode: 0644, parent: priv->debugfs_root, NULL, |
923 | fops: &vga_switcheroo_debugfs_fops); |
924 | } |
925 | |
926 | /** |
927 | * vga_switcheroo_process_delayed_switch() - helper for delayed switching |
928 | * |
929 | * Process a delayed switch if one is pending. DRM drivers should call this |
930 | * from their ->lastclose callback. |
931 | * |
932 | * Return: 0 on success. -EINVAL if no delayed switch is pending, if the client |
933 | * has unregistered in the meantime or if there are other clients blocking the |
934 | * switch. If the actual switch fails, an error is reported and 0 is returned. |
935 | */ |
936 | int vga_switcheroo_process_delayed_switch(void) |
937 | { |
938 | struct vga_switcheroo_client *client; |
939 | int ret; |
940 | int err = -EINVAL; |
941 | |
942 | mutex_lock(&vgasr_mutex); |
943 | if (!vgasr_priv.delayed_switch_active) |
944 | goto err; |
945 | |
946 | pr_info("processing delayed switch to %d\n" , |
947 | vgasr_priv.delayed_client_id); |
948 | |
949 | client = find_client_from_id(head: &vgasr_priv.clients, |
950 | client_id: vgasr_priv.delayed_client_id); |
951 | if (!client || !check_can_switch()) |
952 | goto err; |
953 | |
954 | ret = vga_switchto_stage2(new_client: client); |
955 | if (ret) |
956 | pr_err("delayed switching failed stage 2 %d\n" , ret); |
957 | |
958 | vgasr_priv.delayed_switch_active = false; |
959 | err = 0; |
960 | err: |
961 | mutex_unlock(lock: &vgasr_mutex); |
962 | return err; |
963 | } |
964 | EXPORT_SYMBOL(vga_switcheroo_process_delayed_switch); |
965 | |
966 | /** |
967 | * DOC: Driver power control |
968 | * |
969 | * In this mode of use, the discrete GPU automatically powers up and down at |
970 | * the discretion of the driver's runtime pm. On muxed machines, the user may |
971 | * still influence the muxer state by way of the debugfs interface, however |
972 | * the ON and OFF commands become a no-op for the discrete GPU. |
973 | * |
974 | * This mode is the default on Nvidia HybridPower/Optimus and ATI PowerXpress. |
975 | * Specifying nouveau.runpm=0, radeon.runpm=0 or amdgpu.runpm=0 on the kernel |
976 | * command line disables it. |
977 | * |
978 | * After the GPU has been suspended, the handler needs to be called to cut |
979 | * power to the GPU. Likewise it needs to reinstate power before the GPU |
980 | * can resume. This is achieved by vga_switcheroo_init_domain_pm_ops(), |
981 | * which augments the GPU's suspend/resume functions by the requisite |
982 | * calls to the handler. |
983 | * |
984 | * When the audio device resumes, the GPU needs to be woken. This is achieved |
985 | * by a PCI quirk which calls device_link_add() to declare a dependency on the |
986 | * GPU. That way, the GPU is kept awake whenever and as long as the audio |
987 | * device is in use. |
988 | * |
989 | * On muxed machines, if the mux is initially switched to the discrete GPU, |
990 | * the user ends up with a black screen when the GPU powers down after boot. |
991 | * As a workaround, the mux is forced to the integrated GPU on runtime suspend, |
992 | * cf. https://bugs.freedesktop.org/show_bug.cgi?id=75917 |
993 | */ |
994 | |
995 | static void vga_switcheroo_power_switch(struct pci_dev *pdev, |
996 | enum vga_switcheroo_state state) |
997 | { |
998 | struct vga_switcheroo_client *client; |
999 | |
1000 | if (!vgasr_priv.handler->power_state) |
1001 | return; |
1002 | |
1003 | client = find_client_from_pci(head: &vgasr_priv.clients, pdev); |
1004 | if (!client) |
1005 | return; |
1006 | |
1007 | if (!client->driver_power_control) |
1008 | return; |
1009 | |
1010 | vgasr_priv.handler->power_state(client->id, state); |
1011 | } |
1012 | |
1013 | /* switcheroo power domain */ |
1014 | static int vga_switcheroo_runtime_suspend(struct device *dev) |
1015 | { |
1016 | struct pci_dev *pdev = to_pci_dev(dev); |
1017 | int ret; |
1018 | |
1019 | ret = dev->bus->pm->runtime_suspend(dev); |
1020 | if (ret) |
1021 | return ret; |
1022 | mutex_lock(&vgasr_mutex); |
1023 | if (vgasr_priv.handler->switchto) { |
1024 | mutex_lock(&vgasr_priv.mux_hw_lock); |
1025 | vgasr_priv.handler->switchto(VGA_SWITCHEROO_IGD); |
1026 | mutex_unlock(lock: &vgasr_priv.mux_hw_lock); |
1027 | } |
1028 | pci_bus_set_current_state(bus: pdev->bus, PCI_D3cold); |
1029 | vga_switcheroo_power_switch(pdev, state: VGA_SWITCHEROO_OFF); |
1030 | mutex_unlock(lock: &vgasr_mutex); |
1031 | return 0; |
1032 | } |
1033 | |
1034 | static int vga_switcheroo_runtime_resume(struct device *dev) |
1035 | { |
1036 | struct pci_dev *pdev = to_pci_dev(dev); |
1037 | |
1038 | mutex_lock(&vgasr_mutex); |
1039 | vga_switcheroo_power_switch(pdev, state: VGA_SWITCHEROO_ON); |
1040 | mutex_unlock(lock: &vgasr_mutex); |
1041 | pci_resume_bus(bus: pdev->bus); |
1042 | return dev->bus->pm->runtime_resume(dev); |
1043 | } |
1044 | |
1045 | /** |
1046 | * vga_switcheroo_init_domain_pm_ops() - helper for driver power control |
1047 | * @dev: vga client device |
1048 | * @domain: power domain |
1049 | * |
1050 | * Helper for GPUs whose power state is controlled by the driver's runtime pm. |
1051 | * After the GPU has been suspended, the handler needs to be called to cut |
1052 | * power to the GPU. Likewise it needs to reinstate power before the GPU |
1053 | * can resume. To this end, this helper augments the suspend/resume functions |
1054 | * by the requisite calls to the handler. It needs only be called on platforms |
1055 | * where the power switch is separate to the device being powered down. |
1056 | */ |
1057 | int vga_switcheroo_init_domain_pm_ops(struct device *dev, |
1058 | struct dev_pm_domain *domain) |
1059 | { |
1060 | /* copy over all the bus versions */ |
1061 | if (dev->bus && dev->bus->pm) { |
1062 | domain->ops = *dev->bus->pm; |
1063 | domain->ops.runtime_suspend = vga_switcheroo_runtime_suspend; |
1064 | domain->ops.runtime_resume = vga_switcheroo_runtime_resume; |
1065 | |
1066 | dev_pm_domain_set(dev, pd: domain); |
1067 | return 0; |
1068 | } |
1069 | dev_pm_domain_set(dev, NULL); |
1070 | return -EINVAL; |
1071 | } |
1072 | EXPORT_SYMBOL(vga_switcheroo_init_domain_pm_ops); |
1073 | |
1074 | void vga_switcheroo_fini_domain_pm_ops(struct device *dev) |
1075 | { |
1076 | dev_pm_domain_set(dev, NULL); |
1077 | } |
1078 | EXPORT_SYMBOL(vga_switcheroo_fini_domain_pm_ops); |
1079 | |