Lines Matching +full:gpu +full:- +full:id
2 * vga_switcheroo.c - Support for laptop with dual GPU using one set of outputs
33 #include <linux/apple-gmux.h>
66 * for the inactive GPU.) Also, muxes are often used to cut power to the
67 * discrete GPU while it is not used.
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
75 * suspend/resume order when changing the discrete GPU's power state. In total
77 * client (on the discrete GPU). The code is mostly prepared to support
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
93 * struct vga_switcheroo_client - registered client
99 * @id: client identifier. Determining the id requires the handler,
101 * and later given their true id in vga_switcheroo_enable()
105 * interface is a no-op so as not to interfere with runtime pm
107 * @vga_dev: pci device, indicate which GPU is bound to current audio client
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
118 enum vga_switcheroo_client_id id; member
131 * struct vgasr_priv - vga_switcheroo private data
166 #define client_is_audio(c) ((c)->id & ID_BIT_AUDIO)
168 #define client_id(c) ((c)->id & ~ID_BIT_AUDIO)
192 if (vgasr_priv.handler->init) in vga_switcheroo_enable()
193 vgasr_priv.handler->init(); in vga_switcheroo_enable()
200 ret = vgasr_priv.handler->get_client_id(client->pdev); in vga_switcheroo_enable()
204 client->id = ret; in vga_switcheroo_enable()
212 ret = vgasr_priv.handler->get_client_id(client->vga_dev); in vga_switcheroo_enable()
216 client->id = ret | ID_BIT_AUDIO; in vga_switcheroo_enable()
217 if (client->ops->gpu_bound) in vga_switcheroo_enable()
218 client->ops->gpu_bound(client->pdev, ret); in vga_switcheroo_enable()
226 * vga_switcheroo_register_handler() - register handler
233 * Return: 0 on success, -EINVAL if a handler was already registered.
242 return -EINVAL; in vga_switcheroo_register_handler()
257 * vga_switcheroo_unregister_handler() - unregister handler
278 * vga_switcheroo_handler_flags() - obtain handler flags
293 enum vga_switcheroo_client_id id, in register_client() argument
302 return -ENOMEM; in register_client()
304 client->pwr_state = VGA_SWITCHEROO_ON; in register_client()
305 client->pdev = pdev; in register_client()
306 client->ops = ops; in register_client()
307 client->id = id; in register_client()
308 client->active = active; in register_client()
309 client->driver_power_control = driver_power_control; in register_client()
310 client->vga_dev = vga_dev; in register_client()
313 list_add_tail(&client->list, &vgasr_priv.clients); in register_client()
326 * vga_switcheroo_register_client - register vga client
332 * Register vga client (GPU). Enable vga_switcheroo if another GPU and a
337 * Return: 0 on success, -ENOMEM on memory allocation error.
350 * vga_switcheroo_register_audio_client - register audio client
355 * Register audio client (audio device on a GPU). The client is assumed
359 * Return: 0 on success, -ENOMEM on memory allocation error, -EINVAL on getting
360 * client id error.
366 enum vga_switcheroo_client_id id = VGA_SWITCHEROO_UNKNOWN_ID; in vga_switcheroo_register_audio_client() local
369 * if vga_switcheroo has enabled, that mean two GPU clients and also in vga_switcheroo_register_audio_client()
370 * handler are registered. Get audio client id from bound GPU client in vga_switcheroo_register_audio_client()
371 * id directly, otherwise, set it as VGA_SWITCHEROO_UNKNOWN_ID, in vga_switcheroo_register_audio_client()
372 * it will set to correct id in later when vga_switcheroo_enable() in vga_switcheroo_register_audio_client()
377 id = vgasr_priv.handler->get_client_id(vga_dev); in vga_switcheroo_register_audio_client()
378 if (id < 0) { in vga_switcheroo_register_audio_client()
380 return -EINVAL; in vga_switcheroo_register_audio_client()
382 /* notify if GPU has been already bound */ in vga_switcheroo_register_audio_client()
383 if (ops->gpu_bound) in vga_switcheroo_register_audio_client()
384 ops->gpu_bound(pdev, id); in vga_switcheroo_register_audio_client()
388 return register_client(pdev, ops, id | ID_BIT_AUDIO, vga_dev, in vga_switcheroo_register_audio_client()
399 if (client->pdev == pdev) in find_client_from_pci()
411 if (client->id == client_id) in find_client_from_id()
422 if (client->active) in find_active_client()
428 * vga_switcheroo_client_probe_defer() - whether to defer probing a given client
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
440 if ((pdev->class >> 16) == PCI_BASE_CLASS_DISPLAY) { in vga_switcheroo_client_probe_defer()
442 * apple-gmux is needed on pre-retina MacBook Pro in vga_switcheroo_client_probe_defer()
443 * to probe the panel if pdev is the inactive GPU. in vga_switcheroo_client_probe_defer()
457 if (client->driver_power_control) in vga_switcheroo_pwr_state()
458 if (pm_runtime_enabled(&client->pdev->dev) && in vga_switcheroo_pwr_state()
459 pm_runtime_active(&client->pdev->dev)) in vga_switcheroo_pwr_state()
464 return client->pwr_state; in vga_switcheroo_pwr_state()
468 * vga_switcheroo_get_client_state() - obtain power state of a given client
493 * vga_switcheroo_unregister_client() - unregister client
496 * Unregister client. Disable vga_switcheroo if this is a vga client (GPU).
506 vgasr_priv.registered_clients--; in vga_switcheroo_unregister_client()
507 list_del(&client->list); in vga_switcheroo_unregister_client()
520 * vga_switcheroo_client_fb_set() - set framebuffer of a given client
535 client->fb_info = info; in vga_switcheroo_client_fb_set()
541 * vga_switcheroo_lock_ddc() - temporarily switch DDC lines to a given client
551 * Specifically, %-ENODEV if no handler has registered or if the handler
561 enum vga_switcheroo_client_id id; in vga_switcheroo_lock_ddc() local
564 if (!vgasr_priv.handler || !vgasr_priv.handler->switch_ddc) { in vga_switcheroo_lock_ddc()
565 vgasr_priv.old_ddc_owner = -ENODEV; in vga_switcheroo_lock_ddc()
566 return -ENODEV; in vga_switcheroo_lock_ddc()
569 id = vgasr_priv.handler->get_client_id(pdev); in vga_switcheroo_lock_ddc()
570 vgasr_priv.old_ddc_owner = vgasr_priv.handler->switch_ddc(id); in vga_switcheroo_lock_ddc()
576 * vga_switcheroo_unlock_ddc() - switch DDC lines back to previous owner
585 * Specifically, %-ENODEV if no handler has registered or if the handler
589 * first is not allowed and will result in %-EINVAL.
593 enum vga_switcheroo_client_id id; in vga_switcheroo_unlock_ddc() local
597 return -EINVAL; in vga_switcheroo_unlock_ddc()
600 id = vgasr_priv.handler->get_client_id(pdev); in vga_switcheroo_unlock_ddc()
601 if (vgasr_priv.old_ddc_owner != id) in vga_switcheroo_unlock_ddc()
602 ret = vgasr_priv.handler->switch_ddc( in vga_switcheroo_unlock_ddc()
616 * two GPU drivers and one handler have registered with vga_switcheroo.
622 * Power on the integrated GPU if necessary, power off the discrete GPU.
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.
637 * * MDIS: Mux-only switch to the discrete graphics device.
640 * the ON and OFF commands are a no-op (see next section).
656 client_is_vga(client) ? "" : "-Audio", in vga_switcheroo_show()
657 client->active ? '+' : ' ', in vga_switcheroo_show()
658 client->driver_power_control ? "Dyn" : "", in vga_switcheroo_show()
660 pci_name(client->pdev)); in vga_switcheroo_show()
674 if (client->driver_power_control) in vga_switchon()
676 if (vgasr_priv.handler->power_state) in vga_switchon()
677 vgasr_priv.handler->power_state(client->id, VGA_SWITCHEROO_ON); in vga_switchon()
679 client->ops->set_gpu_state(client->pdev, VGA_SWITCHEROO_ON); in vga_switchon()
680 client->pwr_state = VGA_SWITCHEROO_ON; in vga_switchon()
686 if (client->driver_power_control) in vga_switchoff()
689 client->ops->set_gpu_state(client->pdev, VGA_SWITCHEROO_OFF); in vga_switchoff()
690 if (vgasr_priv.handler->power_state) in vga_switchoff()
691 vgasr_priv.handler->power_state(client->id, VGA_SWITCHEROO_OFF); in vga_switchoff()
692 client->pwr_state = VGA_SWITCHEROO_OFF; in vga_switchoff()
696 static void set_audio_state(enum vga_switcheroo_client_id id, in set_audio_state() argument
701 client = find_client_from_id(&vgasr_priv.clients, id | ID_BIT_AUDIO); in set_audio_state()
703 client->ops->set_gpu_state(client->pdev, state); in set_audio_state()
718 vga_set_default_device(new_client->pdev); in vga_switchto_stage1()
732 active->active = false; in vga_switchto_stage2()
734 /* let HDA controller autosuspend if GPU uses driver power control */ in vga_switchto_stage2()
735 if (!active->driver_power_control) in vga_switchto_stage2()
736 set_audio_state(active->id, VGA_SWITCHEROO_OFF); in vga_switchto_stage2()
738 if (new_client->fb_info) in vga_switchto_stage2()
739 fbcon_remap_all(new_client->fb_info); in vga_switchto_stage2()
742 ret = vgasr_priv.handler->switchto(new_client->id); in vga_switchto_stage2()
747 if (new_client->ops->reprobe) in vga_switchto_stage2()
748 new_client->ops->reprobe(new_client->pdev); in vga_switchto_stage2()
753 /* let HDA controller autoresume if GPU uses driver power control */ in vga_switchto_stage2()
754 if (!new_client->driver_power_control) in vga_switchto_stage2()
755 set_audio_state(new_client->id, VGA_SWITCHEROO_ON); in vga_switchto_stage2()
757 new_client->active = true; in vga_switchto_stage2()
766 if (!client->ops->can_switch(client->pdev)) { in check_can_switch()
767 pr_err("client %x refused switch\n", client->id); in check_can_switch()
789 return -EFAULT; in vga_switcheroo_debugfs_write()
794 cnt = -EINVAL; in vga_switcheroo_debugfs_write()
801 if (client->active || client_is_audio(client)) in vga_switcheroo_debugfs_write()
803 if (client->driver_power_control) in vga_switcheroo_debugfs_write()
805 set_audio_state(client->id, VGA_SWITCHEROO_OFF); in vga_switcheroo_debugfs_write()
806 if (client->pwr_state == VGA_SWITCHEROO_ON) in vga_switcheroo_debugfs_write()
814 if (client->active || client_is_audio(client)) in vga_switcheroo_debugfs_write()
816 if (client->driver_power_control) in vga_switcheroo_debugfs_write()
818 if (client->pwr_state == VGA_SWITCHEROO_OFF) in vga_switcheroo_debugfs_write()
820 set_audio_state(client->id, VGA_SWITCHEROO_ON); in vga_switcheroo_debugfs_write()
825 /* request a delayed switch - test can we switch now */ in vga_switcheroo_debugfs_write()
861 ret = vgasr_priv.handler->switchto(client_id); in vga_switcheroo_debugfs_write()
866 if (client->active) in vga_switcheroo_debugfs_write()
869 /* okay we want a switch - test if devices are willing to switch */ in vga_switcheroo_debugfs_write()
885 pr_info("setting delayed switch to client %d\n", client->id); in vga_switcheroo_debugfs_write()
910 debugfs_remove_recursive(priv->debugfs_root); in vga_switcheroo_debugfs_fini()
911 priv->debugfs_root = NULL; in vga_switcheroo_debugfs_fini()
917 if (priv->debugfs_root) in vga_switcheroo_debugfs_init()
920 priv->debugfs_root = debugfs_create_dir("vgaswitcheroo", NULL); in vga_switcheroo_debugfs_init()
922 debugfs_create_file("switch", 0644, priv->debugfs_root, NULL, in vga_switcheroo_debugfs_init()
927 * vga_switcheroo_process_delayed_switch() - helper for delayed switching
931 * Return: 0 on success. -EINVAL if no delayed switch is pending, if the client
939 int err = -EINVAL; in vga_switcheroo_process_delayed_switch()
968 * In this mode of use, the discrete GPU automatically powers up and down at
971 * the ON and OFF commands become a no-op for the discrete GPU.
977 * After the GPU has been suspended, the handler needs to be called to cut
978 * power to the GPU. Likewise it needs to reinstate power before the GPU
980 * which augments the GPU's suspend/resume functions by the requisite
983 * When the audio device resumes, the GPU needs to be woken. This is achieved
985 * GPU. That way, the GPU is kept awake whenever and as long as the audio
988 * On muxed machines, if the mux is initially switched to the discrete GPU,
989 * the user ends up with a black screen when the GPU powers down after boot.
990 * As a workaround, the mux is forced to the integrated GPU on runtime suspend,
991 * cf. https://bugs.freedesktop.org/show_bug.cgi?id=75917
999 if (!vgasr_priv.handler->power_state) in vga_switcheroo_power_switch()
1006 if (!client->driver_power_control) in vga_switcheroo_power_switch()
1009 vgasr_priv.handler->power_state(client->id, state); in vga_switcheroo_power_switch()
1018 ret = dev->bus->pm->runtime_suspend(dev); in vga_switcheroo_runtime_suspend()
1022 if (vgasr_priv.handler->switchto) { in vga_switcheroo_runtime_suspend()
1024 vgasr_priv.handler->switchto(VGA_SWITCHEROO_IGD); in vga_switcheroo_runtime_suspend()
1027 pci_bus_set_current_state(pdev->bus, PCI_D3cold); in vga_switcheroo_runtime_suspend()
1040 pci_resume_bus(pdev->bus); in vga_switcheroo_runtime_resume()
1041 return dev->bus->pm->runtime_resume(dev); in vga_switcheroo_runtime_resume()
1045 * vga_switcheroo_init_domain_pm_ops() - helper for driver power control
1050 * After the GPU has been suspended, the handler needs to be called to cut
1051 * power to the GPU. Likewise it needs to reinstate power before the GPU
1060 if (dev->bus && dev->bus->pm) { in vga_switcheroo_init_domain_pm_ops()
1061 domain->ops = *dev->bus->pm; in vga_switcheroo_init_domain_pm_ops()
1062 domain->ops.runtime_suspend = vga_switcheroo_runtime_suspend; in vga_switcheroo_init_domain_pm_ops()
1063 domain->ops.runtime_resume = vga_switcheroo_runtime_resume; in vga_switcheroo_init_domain_pm_ops()
1069 return -EINVAL; in vga_switcheroo_init_domain_pm_ops()