Lines Matching +full:client +full:- +full:id
2 * vga_switcheroo.c - Support for laptop with dual GPU using one set of outputs
33 #include <linux/apple-gmux.h>
70 * handler to control the power state of the discrete GPU, its ->switchto
71 * callback is a no-op for obvious reasons. The discrete GPU is often equipped
73 * register as a client so that vga_switcheroo can take care of the correct
76 * client (on the discrete GPU). The code is mostly prepared to support
80 * active client in vga_switcheroo parlance. The GPU not in use is the
81 * inactive client. When the inactive client's DRM driver is loaded,
85 * a client may alternatively request that the DDC lines are temporarily
92 * struct vga_switcheroo_client - registered client
93 * @pdev: client pci device
97 * @ops: client callbacks
98 * @id: client identifier. Determining the id requires the handler,
100 * and later given their true id in vga_switcheroo_enable()
101 * @active: whether the outputs are currently switched to this client
104 * interface is a no-op so as not to interfere with runtime pm
105 * @list: client list
106 * @vga_dev: pci device, indicate which GPU is bound to current audio client
108 * Registered client. A client can be either a GPU or an audio device on a GPU.
117 enum vga_switcheroo_client_id id; member
130 * struct vgasr_priv - vga_switcheroo private data
134 * @delayed_client_id: client to which a delayed switch is pending
144 * @old_ddc_owner: client to which DDC lines will be switched back on unlock
167 #define client_is_audio(c) ((c)->id & ID_BIT_AUDIO)
169 #define client_id(c) ((c)->id & ~ID_BIT_AUDIO)
190 struct vga_switcheroo_client *client; in vga_switcheroo_enable() local
193 if (vgasr_priv.handler->init) in vga_switcheroo_enable()
194 vgasr_priv.handler->init(); in vga_switcheroo_enable()
196 list_for_each_entry(client, &vgasr_priv.clients, list) { in vga_switcheroo_enable()
197 if (!client_is_vga(client) || in vga_switcheroo_enable()
198 client_id(client) != VGA_SWITCHEROO_UNKNOWN_ID) in vga_switcheroo_enable()
201 ret = vgasr_priv.handler->get_client_id(client->pdev); in vga_switcheroo_enable()
205 client->id = ret; in vga_switcheroo_enable()
208 list_for_each_entry(client, &vgasr_priv.clients, list) { in vga_switcheroo_enable()
209 if (!client_is_audio(client) || in vga_switcheroo_enable()
210 client_id(client) != VGA_SWITCHEROO_UNKNOWN_ID) in vga_switcheroo_enable()
213 ret = vgasr_priv.handler->get_client_id(client->vga_dev); in vga_switcheroo_enable()
217 client->id = ret | ID_BIT_AUDIO; in vga_switcheroo_enable()
218 if (client->ops->gpu_bound) in vga_switcheroo_enable()
219 client->ops->gpu_bound(client->pdev, ret); in vga_switcheroo_enable()
227 * vga_switcheroo_register_handler() - register handler
234 * Return: 0 on success, -EINVAL if a handler was already registered.
243 return -EINVAL; in vga_switcheroo_register_handler()
258 * vga_switcheroo_unregister_handler() - unregister handler
279 * vga_switcheroo_handler_flags() - obtain handler flags
294 enum vga_switcheroo_client_id id, in register_client() argument
299 struct vga_switcheroo_client *client; in register_client() local
301 client = kzalloc(sizeof(*client), GFP_KERNEL); in register_client()
302 if (!client) in register_client()
303 return -ENOMEM; in register_client()
305 client->pwr_state = VGA_SWITCHEROO_ON; in register_client()
306 client->pdev = pdev; in register_client()
307 client->ops = ops; in register_client()
308 client->id = id; in register_client()
309 client->active = active; in register_client()
310 client->driver_power_control = driver_power_control; in register_client()
311 client->vga_dev = vga_dev; in register_client()
314 list_add_tail(&client->list, &vgasr_priv.clients); in register_client()
315 if (client_is_vga(client)) in register_client()
327 * vga_switcheroo_register_client - register vga client
328 * @pdev: client pci device
329 * @ops: client callbacks
333 * Register vga client (GPU). Enable vga_switcheroo if another GPU and a
334 * handler have already registered. The power state of the client is assumed
338 * Return: 0 on success, -ENOMEM on memory allocation error.
351 * vga_switcheroo_register_audio_client - register audio client
352 * @pdev: client pci device
353 * @ops: client callbacks
354 * @vga_dev: pci device which is bound to current audio client
356 * Register audio client (audio device on a GPU). The client is assumed
360 * Return: 0 on success, -ENOMEM on memory allocation error, -EINVAL on getting
361 * client id error.
367 enum vga_switcheroo_client_id id = VGA_SWITCHEROO_UNKNOWN_ID; in vga_switcheroo_register_audio_client() local
371 * handler are registered. Get audio client id from bound GPU client in vga_switcheroo_register_audio_client()
372 * id directly, otherwise, set it as VGA_SWITCHEROO_UNKNOWN_ID, in vga_switcheroo_register_audio_client()
373 * it will set to correct id in later when vga_switcheroo_enable() in vga_switcheroo_register_audio_client()
378 id = vgasr_priv.handler->get_client_id(vga_dev); in vga_switcheroo_register_audio_client()
379 if (id < 0) { in vga_switcheroo_register_audio_client()
381 return -EINVAL; in vga_switcheroo_register_audio_client()
384 if (ops->gpu_bound) in vga_switcheroo_register_audio_client()
385 ops->gpu_bound(pdev, id); in vga_switcheroo_register_audio_client()
389 return register_client(pdev, ops, id | ID_BIT_AUDIO, vga_dev, in vga_switcheroo_register_audio_client()
397 struct vga_switcheroo_client *client; in find_client_from_pci() local
399 list_for_each_entry(client, head, list) in find_client_from_pci()
400 if (client->pdev == pdev) in find_client_from_pci()
401 return client; in find_client_from_pci()
409 struct vga_switcheroo_client *client; in find_client_from_id() local
411 list_for_each_entry(client, head, list) in find_client_from_id()
412 if (client->id == client_id) in find_client_from_id()
413 return client; in find_client_from_id()
420 struct vga_switcheroo_client *client; in find_active_client() local
422 list_for_each_entry(client, head, list) in find_active_client()
423 if (client->active) in find_active_client()
424 return client; in find_active_client()
429 * vga_switcheroo_client_probe_defer() - whether to defer probing a given client
430 * @pdev: client pci device
433 * client. Drivers shall invoke this early on in their ->probe callback
434 * and return %-EPROBE_DEFER if it evaluates to %true. Thou shalt not
435 * register the client ere thou hast called this.
441 if ((pdev->class >> 16) == PCI_BASE_CLASS_DISPLAY) { in vga_switcheroo_client_probe_defer()
443 * apple-gmux is needed on pre-retina MacBook Pro in vga_switcheroo_client_probe_defer()
456 vga_switcheroo_pwr_state(struct vga_switcheroo_client *client) in vga_switcheroo_pwr_state() argument
458 if (client->driver_power_control) in vga_switcheroo_pwr_state()
459 if (pm_runtime_enabled(&client->pdev->dev) && in vga_switcheroo_pwr_state()
460 pm_runtime_active(&client->pdev->dev)) in vga_switcheroo_pwr_state()
465 return client->pwr_state; in vga_switcheroo_pwr_state()
469 * vga_switcheroo_get_client_state() - obtain power state of a given client
470 * @pdev: client pci device
472 * Obtain power state of a given client as seen from vga_switcheroo.
479 struct vga_switcheroo_client *client; in vga_switcheroo_get_client_state() local
483 client = find_client_from_pci(&vgasr_priv.clients, pdev); in vga_switcheroo_get_client_state()
484 if (!client) in vga_switcheroo_get_client_state()
487 ret = vga_switcheroo_pwr_state(client); in vga_switcheroo_get_client_state()
494 * vga_switcheroo_unregister_client() - unregister client
495 * @pdev: client pci device
497 * Unregister client. Disable vga_switcheroo if this is a vga client (GPU).
501 struct vga_switcheroo_client *client; in vga_switcheroo_unregister_client() local
504 client = find_client_from_pci(&vgasr_priv.clients, pdev); in vga_switcheroo_unregister_client()
505 if (client) { in vga_switcheroo_unregister_client()
506 if (client_is_vga(client)) in vga_switcheroo_unregister_client()
507 vgasr_priv.registered_clients--; in vga_switcheroo_unregister_client()
508 list_del(&client->list); in vga_switcheroo_unregister_client()
509 kfree(client); in vga_switcheroo_unregister_client()
521 * vga_switcheroo_client_fb_set() - set framebuffer of a given client
522 * @pdev: client pci device
525 * Set framebuffer of a given client. The console will be remapped to this
531 struct vga_switcheroo_client *client; in vga_switcheroo_client_fb_set() local
534 client = find_client_from_pci(&vgasr_priv.clients, pdev); in vga_switcheroo_client_fb_set()
535 if (client) in vga_switcheroo_client_fb_set()
536 client->fb_info = info; in vga_switcheroo_client_fb_set()
542 * vga_switcheroo_lock_ddc() - temporarily switch DDC lines to a given client
543 * @pdev: client pci device
545 * Temporarily switch DDC lines to the client identified by @pdev
547 * This allows the inactive client to probe EDID. The DDC lines must
552 * Specifically, %-ENODEV if no handler has registered or if the handler
562 enum vga_switcheroo_client_id id; in vga_switcheroo_lock_ddc() local
565 if (!vgasr_priv.handler || !vgasr_priv.handler->switch_ddc) { in vga_switcheroo_lock_ddc()
566 vgasr_priv.old_ddc_owner = -ENODEV; in vga_switcheroo_lock_ddc()
567 return -ENODEV; in vga_switcheroo_lock_ddc()
570 id = vgasr_priv.handler->get_client_id(pdev); in vga_switcheroo_lock_ddc()
571 vgasr_priv.old_ddc_owner = vgasr_priv.handler->switch_ddc(id); in vga_switcheroo_lock_ddc()
577 * vga_switcheroo_unlock_ddc() - switch DDC lines back to previous owner
578 * @pdev: client pci device
584 * Return: Previous DDC owner on success (i.e. the client identifier of @pdev)
586 * Specifically, %-ENODEV if no handler has registered or if the handler
590 * first is not allowed and will result in %-EINVAL.
594 enum vga_switcheroo_client_id id; in vga_switcheroo_unlock_ddc() local
598 return -EINVAL; in vga_switcheroo_unlock_ddc()
601 id = vgasr_priv.handler->get_client_id(pdev); in vga_switcheroo_unlock_ddc()
602 if (vgasr_priv.old_ddc_owner != id) in vga_switcheroo_unlock_ddc()
603 ret = vgasr_priv.handler->switch_ddc( in vga_switcheroo_unlock_ddc()
625 * have opened device files of the GPUs or the audio client. If the
631 * closed the device files of the GPUs and the audio client.
633 * * MIGD: Mux-only switch to the integrated graphics device.
638 * * MDIS: Mux-only switch to the discrete graphics device.
641 * the ON and OFF commands are a no-op (see next section).
649 struct vga_switcheroo_client *client; in vga_switcheroo_show() local
653 list_for_each_entry(client, &vgasr_priv.clients, list) { in vga_switcheroo_show()
655 client_id(client) == VGA_SWITCHEROO_DIS ? "DIS" : in vga_switcheroo_show()
657 client_is_vga(client) ? "" : "-Audio", in vga_switcheroo_show()
658 client->active ? '+' : ' ', in vga_switcheroo_show()
659 client->driver_power_control ? "Dyn" : "", in vga_switcheroo_show()
660 vga_switcheroo_pwr_state(client) ? "Pwr" : "Off", in vga_switcheroo_show()
661 pci_name(client->pdev)); in vga_switcheroo_show()
673 static int vga_switchon(struct vga_switcheroo_client *client) in vga_switchon() argument
675 if (client->driver_power_control) in vga_switchon()
677 if (vgasr_priv.handler->power_state) in vga_switchon()
678 vgasr_priv.handler->power_state(client->id, VGA_SWITCHEROO_ON); in vga_switchon()
680 client->ops->set_gpu_state(client->pdev, VGA_SWITCHEROO_ON); in vga_switchon()
681 client->pwr_state = VGA_SWITCHEROO_ON; in vga_switchon()
685 static int vga_switchoff(struct vga_switcheroo_client *client) in vga_switchoff() argument
687 if (client->driver_power_control) in vga_switchoff()
690 client->ops->set_gpu_state(client->pdev, VGA_SWITCHEROO_OFF); in vga_switchoff()
691 if (vgasr_priv.handler->power_state) in vga_switchoff()
692 vgasr_priv.handler->power_state(client->id, VGA_SWITCHEROO_OFF); in vga_switchoff()
693 client->pwr_state = VGA_SWITCHEROO_OFF; in vga_switchoff()
697 static void set_audio_state(enum vga_switcheroo_client_id id, in set_audio_state() argument
700 struct vga_switcheroo_client *client; in set_audio_state() local
702 client = find_client_from_id(&vgasr_priv.clients, id | ID_BIT_AUDIO); in set_audio_state()
703 if (client) in set_audio_state()
704 client->ops->set_gpu_state(client->pdev, state); in set_audio_state()
719 vga_set_default_device(new_client->pdev); in vga_switchto_stage1()
733 active->active = false; in vga_switchto_stage2()
736 if (!active->driver_power_control) in vga_switchto_stage2()
737 set_audio_state(active->id, VGA_SWITCHEROO_OFF); in vga_switchto_stage2()
739 if (new_client->fb_info) { in vga_switchto_stage2()
743 event.info = new_client->fb_info; in vga_switchto_stage2()
749 ret = vgasr_priv.handler->switchto(new_client->id); in vga_switchto_stage2()
754 if (new_client->ops->reprobe) in vga_switchto_stage2()
755 new_client->ops->reprobe(new_client->pdev); in vga_switchto_stage2()
761 if (!new_client->driver_power_control) in vga_switchto_stage2()
762 set_audio_state(new_client->id, VGA_SWITCHEROO_ON); in vga_switchto_stage2()
764 new_client->active = true; in vga_switchto_stage2()
770 struct vga_switcheroo_client *client; in check_can_switch() local
772 list_for_each_entry(client, &vgasr_priv.clients, list) { in check_can_switch()
773 if (!client->ops->can_switch(client->pdev)) { in check_can_switch()
774 pr_err("client %x refused switch\n", client->id); in check_can_switch()
790 struct vga_switcheroo_client *client = NULL; in vga_switcheroo_debugfs_write() local
796 return -EFAULT; in vga_switcheroo_debugfs_write()
801 cnt = -EINVAL; in vga_switcheroo_debugfs_write()
807 list_for_each_entry(client, &vgasr_priv.clients, list) { in vga_switcheroo_debugfs_write()
808 if (client->active || client_is_audio(client)) in vga_switcheroo_debugfs_write()
810 if (client->driver_power_control) in vga_switcheroo_debugfs_write()
812 set_audio_state(client->id, VGA_SWITCHEROO_OFF); in vga_switcheroo_debugfs_write()
813 if (client->pwr_state == VGA_SWITCHEROO_ON) in vga_switcheroo_debugfs_write()
814 vga_switchoff(client); in vga_switcheroo_debugfs_write()
820 list_for_each_entry(client, &vgasr_priv.clients, list) { in vga_switcheroo_debugfs_write()
821 if (client->active || client_is_audio(client)) in vga_switcheroo_debugfs_write()
823 if (client->driver_power_control) in vga_switcheroo_debugfs_write()
825 if (client->pwr_state == VGA_SWITCHEROO_OFF) in vga_switcheroo_debugfs_write()
826 vga_switchon(client); in vga_switcheroo_debugfs_write()
827 set_audio_state(client->id, VGA_SWITCHEROO_ON); in vga_switcheroo_debugfs_write()
832 /* request a delayed switch - test can we switch now */ in vga_switcheroo_debugfs_write()
860 client = find_client_from_id(&vgasr_priv.clients, client_id); in vga_switcheroo_debugfs_write()
861 if (!client) in vga_switcheroo_debugfs_write()
868 ret = vgasr_priv.handler->switchto(client_id); in vga_switcheroo_debugfs_write()
873 if (client->active) in vga_switcheroo_debugfs_write()
876 /* okay we want a switch - test if devices are willing to switch */ in vga_switcheroo_debugfs_write()
883 ret = vga_switchto_stage1(client); in vga_switcheroo_debugfs_write()
887 ret = vga_switchto_stage2(client); in vga_switcheroo_debugfs_write()
892 pr_info("setting delayed switch to client %d\n", client->id); in vga_switcheroo_debugfs_write()
896 ret = vga_switchto_stage1(client); in vga_switcheroo_debugfs_write()
917 debugfs_remove(priv->switch_file); in vga_switcheroo_debugfs_fini()
918 priv->switch_file = NULL; in vga_switcheroo_debugfs_fini()
920 debugfs_remove(priv->debugfs_root); in vga_switcheroo_debugfs_fini()
921 priv->debugfs_root = NULL; in vga_switcheroo_debugfs_fini()
929 if (priv->debugfs_root) in vga_switcheroo_debugfs_init()
931 priv->debugfs_root = debugfs_create_dir("vgaswitcheroo", NULL); in vga_switcheroo_debugfs_init()
933 if (!priv->debugfs_root) { in vga_switcheroo_debugfs_init()
938 priv->switch_file = debugfs_create_file("switch", 0644, in vga_switcheroo_debugfs_init()
939 priv->debugfs_root, NULL, in vga_switcheroo_debugfs_init()
941 if (!priv->switch_file) { in vga_switcheroo_debugfs_init()
948 return -1; in vga_switcheroo_debugfs_init()
952 * vga_switcheroo_process_delayed_switch() - helper for delayed switching
955 * from their ->lastclose callback.
957 * Return: 0 on success. -EINVAL if no delayed switch is pending, if the client
963 struct vga_switcheroo_client *client; in vga_switcheroo_process_delayed_switch() local
965 int err = -EINVAL; in vga_switcheroo_process_delayed_switch()
974 client = find_client_from_id(&vgasr_priv.clients, in vga_switcheroo_process_delayed_switch()
976 if (!client || !check_can_switch()) in vga_switcheroo_process_delayed_switch()
979 ret = vga_switchto_stage2(client); in vga_switcheroo_process_delayed_switch()
997 * the ON and OFF commands become a no-op for the discrete GPU.
1017 * cf. https://bugs.freedesktop.org/show_bug.cgi?id=75917
1023 struct vga_switcheroo_client *client; in vga_switcheroo_power_switch() local
1025 if (!vgasr_priv.handler->power_state) in vga_switcheroo_power_switch()
1028 client = find_client_from_pci(&vgasr_priv.clients, pdev); in vga_switcheroo_power_switch()
1029 if (!client) in vga_switcheroo_power_switch()
1032 if (!client->driver_power_control) in vga_switcheroo_power_switch()
1035 vgasr_priv.handler->power_state(client->id, state); in vga_switcheroo_power_switch()
1044 ret = dev->bus->pm->runtime_suspend(dev); in vga_switcheroo_runtime_suspend()
1048 if (vgasr_priv.handler->switchto) { in vga_switcheroo_runtime_suspend()
1050 vgasr_priv.handler->switchto(VGA_SWITCHEROO_IGD); in vga_switcheroo_runtime_suspend()
1053 pci_bus_set_current_state(pdev->bus, PCI_D3cold); in vga_switcheroo_runtime_suspend()
1067 pci_wakeup_bus(pdev->bus); in vga_switcheroo_runtime_resume()
1068 ret = dev->bus->pm->runtime_resume(dev); in vga_switcheroo_runtime_resume()
1076 * vga_switcheroo_init_domain_pm_ops() - helper for driver power control
1077 * @dev: vga client device
1091 if (dev->bus && dev->bus->pm) { in vga_switcheroo_init_domain_pm_ops()
1092 domain->ops = *dev->bus->pm; in vga_switcheroo_init_domain_pm_ops()
1093 domain->ops.runtime_suspend = vga_switcheroo_runtime_suspend; in vga_switcheroo_init_domain_pm_ops()
1094 domain->ops.runtime_resume = vga_switcheroo_runtime_resume; in vga_switcheroo_init_domain_pm_ops()
1100 return -EINVAL; in vga_switcheroo_init_domain_pm_ops()