1 /* 2 * Copyright (c) 2010 Red Hat Inc. 3 * Author : Dave Airlie <airlied@redhat.com> 4 * 5 * 6 * Licensed under GPLv2 7 * 8 * vga_switcheroo.c - Support for laptop with dual GPU using one set of outputs 9 10 Switcher interface - methods require for ATPX and DCM 11 - switchto - this throws the output MUX switch 12 - discrete_set_power - sets the power state for the discrete card 13 14 GPU driver interface 15 - set_gpu_state - this should do the equiv of s/r for the card 16 - this should *not* set the discrete power state 17 - switch_check - check if the device is in a position to switch now 18 */ 19 20 #include <linux/module.h> 21 #include <linux/dmi.h> 22 #include <linux/seq_file.h> 23 #include <linux/uaccess.h> 24 #include <linux/fs.h> 25 #include <linux/debugfs.h> 26 #include <linux/fb.h> 27 28 #include <linux/pci.h> 29 #include <linux/vga_switcheroo.h> 30 31 struct vga_switcheroo_client { 32 struct pci_dev *pdev; 33 struct fb_info *fb_info; 34 int pwr_state; 35 void (*set_gpu_state)(struct pci_dev *pdev, enum vga_switcheroo_state); 36 void (*reprobe)(struct pci_dev *pdev); 37 bool (*can_switch)(struct pci_dev *pdev); 38 int id; 39 bool active; 40 }; 41 42 static DEFINE_MUTEX(vgasr_mutex); 43 44 struct vgasr_priv { 45 46 bool active; 47 bool delayed_switch_active; 48 enum vga_switcheroo_client_id delayed_client_id; 49 50 struct dentry *debugfs_root; 51 struct dentry *switch_file; 52 53 int registered_clients; 54 struct vga_switcheroo_client clients[VGA_SWITCHEROO_MAX_CLIENTS]; 55 56 struct vga_switcheroo_handler *handler; 57 }; 58 59 static int vga_switcheroo_debugfs_init(struct vgasr_priv *priv); 60 static void vga_switcheroo_debugfs_fini(struct vgasr_priv *priv); 61 62 /* only one switcheroo per system */ 63 static struct vgasr_priv vgasr_priv; 64 65 int vga_switcheroo_register_handler(struct vga_switcheroo_handler *handler) 66 { 67 mutex_lock(&vgasr_mutex); 68 if (vgasr_priv.handler) { 69 mutex_unlock(&vgasr_mutex); 70 return -EINVAL; 71 } 72 73 vgasr_priv.handler = handler; 74 mutex_unlock(&vgasr_mutex); 75 return 0; 76 } 77 EXPORT_SYMBOL(vga_switcheroo_register_handler); 78 79 void vga_switcheroo_unregister_handler(void) 80 { 81 mutex_lock(&vgasr_mutex); 82 vgasr_priv.handler = NULL; 83 mutex_unlock(&vgasr_mutex); 84 } 85 EXPORT_SYMBOL(vga_switcheroo_unregister_handler); 86 87 static void vga_switcheroo_enable(void) 88 { 89 int i; 90 int ret; 91 /* call the handler to init */ 92 vgasr_priv.handler->init(); 93 94 for (i = 0; i < VGA_SWITCHEROO_MAX_CLIENTS; i++) { 95 ret = vgasr_priv.handler->get_client_id(vgasr_priv.clients[i].pdev); 96 if (ret < 0) 97 return; 98 99 vgasr_priv.clients[i].id = ret; 100 } 101 vga_switcheroo_debugfs_init(&vgasr_priv); 102 vgasr_priv.active = true; 103 } 104 105 int vga_switcheroo_register_client(struct pci_dev *pdev, 106 void (*set_gpu_state)(struct pci_dev *pdev, enum vga_switcheroo_state), 107 void (*reprobe)(struct pci_dev *pdev), 108 bool (*can_switch)(struct pci_dev *pdev)) 109 { 110 int index; 111 112 mutex_lock(&vgasr_mutex); 113 /* don't do IGD vs DIS here */ 114 if (vgasr_priv.registered_clients & 1) 115 index = 1; 116 else 117 index = 0; 118 119 vgasr_priv.clients[index].pwr_state = VGA_SWITCHEROO_ON; 120 vgasr_priv.clients[index].pdev = pdev; 121 vgasr_priv.clients[index].set_gpu_state = set_gpu_state; 122 vgasr_priv.clients[index].reprobe = reprobe; 123 vgasr_priv.clients[index].can_switch = can_switch; 124 vgasr_priv.clients[index].id = -1; 125 if (pdev->resource[PCI_ROM_RESOURCE].flags & IORESOURCE_ROM_SHADOW) 126 vgasr_priv.clients[index].active = true; 127 128 vgasr_priv.registered_clients |= (1 << index); 129 130 /* if we get two clients + handler */ 131 if (vgasr_priv.registered_clients == 0x3 && vgasr_priv.handler) { 132 printk(KERN_INFO "vga_switcheroo: enabled\n"); 133 vga_switcheroo_enable(); 134 } 135 mutex_unlock(&vgasr_mutex); 136 return 0; 137 } 138 EXPORT_SYMBOL(vga_switcheroo_register_client); 139 140 void vga_switcheroo_unregister_client(struct pci_dev *pdev) 141 { 142 int i; 143 144 mutex_lock(&vgasr_mutex); 145 for (i = 0; i < VGA_SWITCHEROO_MAX_CLIENTS; i++) { 146 if (vgasr_priv.clients[i].pdev == pdev) { 147 vgasr_priv.registered_clients &= ~(1 << i); 148 break; 149 } 150 } 151 152 printk(KERN_INFO "vga_switcheroo: disabled\n"); 153 vga_switcheroo_debugfs_fini(&vgasr_priv); 154 vgasr_priv.active = false; 155 mutex_unlock(&vgasr_mutex); 156 } 157 EXPORT_SYMBOL(vga_switcheroo_unregister_client); 158 159 void vga_switcheroo_client_fb_set(struct pci_dev *pdev, 160 struct fb_info *info) 161 { 162 int i; 163 164 mutex_lock(&vgasr_mutex); 165 for (i = 0; i < VGA_SWITCHEROO_MAX_CLIENTS; i++) { 166 if (vgasr_priv.clients[i].pdev == pdev) { 167 vgasr_priv.clients[i].fb_info = info; 168 break; 169 } 170 } 171 mutex_unlock(&vgasr_mutex); 172 } 173 EXPORT_SYMBOL(vga_switcheroo_client_fb_set); 174 175 static int vga_switcheroo_show(struct seq_file *m, void *v) 176 { 177 int i; 178 mutex_lock(&vgasr_mutex); 179 for (i = 0; i < VGA_SWITCHEROO_MAX_CLIENTS; i++) { 180 seq_printf(m, "%d:%s:%c:%s:%s\n", i, 181 vgasr_priv.clients[i].id == VGA_SWITCHEROO_DIS ? "DIS" : "IGD", 182 vgasr_priv.clients[i].active ? '+' : ' ', 183 vgasr_priv.clients[i].pwr_state ? "Pwr" : "Off", 184 pci_name(vgasr_priv.clients[i].pdev)); 185 } 186 mutex_unlock(&vgasr_mutex); 187 return 0; 188 } 189 190 static int vga_switcheroo_debugfs_open(struct inode *inode, struct file *file) 191 { 192 return single_open(file, vga_switcheroo_show, NULL); 193 } 194 195 static int vga_switchon(struct vga_switcheroo_client *client) 196 { 197 if (vgasr_priv.handler->power_state) 198 vgasr_priv.handler->power_state(client->id, VGA_SWITCHEROO_ON); 199 /* call the driver callback to turn on device */ 200 client->set_gpu_state(client->pdev, VGA_SWITCHEROO_ON); 201 client->pwr_state = VGA_SWITCHEROO_ON; 202 return 0; 203 } 204 205 static int vga_switchoff(struct vga_switcheroo_client *client) 206 { 207 /* call the driver callback to turn off device */ 208 client->set_gpu_state(client->pdev, VGA_SWITCHEROO_OFF); 209 if (vgasr_priv.handler->power_state) 210 vgasr_priv.handler->power_state(client->id, VGA_SWITCHEROO_OFF); 211 client->pwr_state = VGA_SWITCHEROO_OFF; 212 return 0; 213 } 214 215 /* stage one happens before delay */ 216 static int vga_switchto_stage1(struct vga_switcheroo_client *new_client) 217 { 218 int ret; 219 int i; 220 struct vga_switcheroo_client *active = NULL; 221 222 if (new_client->active == true) 223 return 0; 224 225 for (i = 0; i < VGA_SWITCHEROO_MAX_CLIENTS; i++) { 226 if (vgasr_priv.clients[i].active == true) { 227 active = &vgasr_priv.clients[i]; 228 break; 229 } 230 } 231 if (!active) 232 return 0; 233 234 /* power up the first device */ 235 ret = pci_enable_device(new_client->pdev); 236 if (ret) 237 return ret; 238 239 if (new_client->pwr_state == VGA_SWITCHEROO_OFF) 240 vga_switchon(new_client); 241 242 /* swap shadow resource to denote boot VGA device has changed so X starts on new device */ 243 active->pdev->resource[PCI_ROM_RESOURCE].flags &= ~IORESOURCE_ROM_SHADOW; 244 new_client->pdev->resource[PCI_ROM_RESOURCE].flags |= IORESOURCE_ROM_SHADOW; 245 return 0; 246 } 247 248 /* post delay */ 249 static int vga_switchto_stage2(struct vga_switcheroo_client *new_client) 250 { 251 int ret; 252 int i; 253 struct vga_switcheroo_client *active = NULL; 254 255 for (i = 0; i < VGA_SWITCHEROO_MAX_CLIENTS; i++) { 256 if (vgasr_priv.clients[i].active == true) { 257 active = &vgasr_priv.clients[i]; 258 break; 259 } 260 } 261 if (!active) 262 return 0; 263 264 active->active = false; 265 266 if (new_client->fb_info) { 267 struct fb_event event; 268 event.info = new_client->fb_info; 269 fb_notifier_call_chain(FB_EVENT_REMAP_ALL_CONSOLE, &event); 270 } 271 272 ret = vgasr_priv.handler->switchto(new_client->id); 273 if (ret) 274 return ret; 275 276 if (new_client->reprobe) 277 new_client->reprobe(new_client->pdev); 278 279 if (active->pwr_state == VGA_SWITCHEROO_ON) 280 vga_switchoff(active); 281 282 new_client->active = true; 283 return 0; 284 } 285 286 static ssize_t 287 vga_switcheroo_debugfs_write(struct file *filp, const char __user *ubuf, 288 size_t cnt, loff_t *ppos) 289 { 290 char usercmd[64]; 291 const char *pdev_name; 292 int i, ret; 293 bool delay = false, can_switch; 294 bool just_mux = false; 295 int client_id = -1; 296 struct vga_switcheroo_client *client = NULL; 297 298 if (cnt > 63) 299 cnt = 63; 300 301 if (copy_from_user(usercmd, ubuf, cnt)) 302 return -EFAULT; 303 304 mutex_lock(&vgasr_mutex); 305 306 if (!vgasr_priv.active) { 307 cnt = -EINVAL; 308 goto out; 309 } 310 311 /* pwr off the device not in use */ 312 if (strncmp(usercmd, "OFF", 3) == 0) { 313 for (i = 0; i < VGA_SWITCHEROO_MAX_CLIENTS; i++) { 314 if (vgasr_priv.clients[i].active) 315 continue; 316 if (vgasr_priv.clients[i].pwr_state == VGA_SWITCHEROO_ON) 317 vga_switchoff(&vgasr_priv.clients[i]); 318 } 319 goto out; 320 } 321 /* pwr on the device not in use */ 322 if (strncmp(usercmd, "ON", 2) == 0) { 323 for (i = 0; i < VGA_SWITCHEROO_MAX_CLIENTS; i++) { 324 if (vgasr_priv.clients[i].active) 325 continue; 326 if (vgasr_priv.clients[i].pwr_state == VGA_SWITCHEROO_OFF) 327 vga_switchon(&vgasr_priv.clients[i]); 328 } 329 goto out; 330 } 331 332 /* request a delayed switch - test can we switch now */ 333 if (strncmp(usercmd, "DIGD", 4) == 0) { 334 client_id = VGA_SWITCHEROO_IGD; 335 delay = true; 336 } 337 338 if (strncmp(usercmd, "DDIS", 4) == 0) { 339 client_id = VGA_SWITCHEROO_DIS; 340 delay = true; 341 } 342 343 if (strncmp(usercmd, "IGD", 3) == 0) 344 client_id = VGA_SWITCHEROO_IGD; 345 346 if (strncmp(usercmd, "DIS", 3) == 0) 347 client_id = VGA_SWITCHEROO_DIS; 348 349 if (strncmp(usercmd, "MIGD", 4) == 0) { 350 just_mux = true; 351 client_id = VGA_SWITCHEROO_IGD; 352 } 353 if (strncmp(usercmd, "MDIS", 4) == 0) { 354 just_mux = true; 355 client_id = VGA_SWITCHEROO_DIS; 356 } 357 358 if (client_id == -1) 359 goto out; 360 361 for (i = 0; i < VGA_SWITCHEROO_MAX_CLIENTS; i++) { 362 if (vgasr_priv.clients[i].id == client_id) { 363 client = &vgasr_priv.clients[i]; 364 break; 365 } 366 } 367 368 vgasr_priv.delayed_switch_active = false; 369 370 if (just_mux) { 371 ret = vgasr_priv.handler->switchto(client_id); 372 goto out; 373 } 374 375 /* okay we want a switch - test if devices are willing to switch */ 376 can_switch = true; 377 for (i = 0; i < VGA_SWITCHEROO_MAX_CLIENTS; i++) { 378 can_switch = vgasr_priv.clients[i].can_switch(vgasr_priv.clients[i].pdev); 379 if (can_switch == false) { 380 printk(KERN_ERR "vga_switcheroo: client %d refused switch\n", i); 381 break; 382 } 383 } 384 385 if (can_switch == false && delay == false) 386 goto out; 387 388 if (can_switch == true) { 389 pdev_name = pci_name(client->pdev); 390 ret = vga_switchto_stage1(client); 391 if (ret) 392 printk(KERN_ERR "vga_switcheroo: switching failed stage 1 %d\n", ret); 393 394 ret = vga_switchto_stage2(client); 395 if (ret) 396 printk(KERN_ERR "vga_switcheroo: switching failed stage 2 %d\n", ret); 397 398 } else { 399 printk(KERN_INFO "vga_switcheroo: setting delayed switch to client %d\n", client->id); 400 vgasr_priv.delayed_switch_active = true; 401 vgasr_priv.delayed_client_id = client_id; 402 403 ret = vga_switchto_stage1(client); 404 if (ret) 405 printk(KERN_ERR "vga_switcheroo: delayed switching stage 1 failed %d\n", ret); 406 } 407 408 out: 409 mutex_unlock(&vgasr_mutex); 410 return cnt; 411 } 412 413 static const struct file_operations vga_switcheroo_debugfs_fops = { 414 .owner = THIS_MODULE, 415 .open = vga_switcheroo_debugfs_open, 416 .write = vga_switcheroo_debugfs_write, 417 .read = seq_read, 418 .llseek = seq_lseek, 419 .release = single_release, 420 }; 421 422 static void vga_switcheroo_debugfs_fini(struct vgasr_priv *priv) 423 { 424 if (priv->switch_file) { 425 debugfs_remove(priv->switch_file); 426 priv->switch_file = NULL; 427 } 428 if (priv->debugfs_root) { 429 debugfs_remove(priv->debugfs_root); 430 priv->debugfs_root = NULL; 431 } 432 } 433 434 static int vga_switcheroo_debugfs_init(struct vgasr_priv *priv) 435 { 436 /* already initialised */ 437 if (priv->debugfs_root) 438 return 0; 439 priv->debugfs_root = debugfs_create_dir("vgaswitcheroo", NULL); 440 441 if (!priv->debugfs_root) { 442 printk(KERN_ERR "vga_switcheroo: Cannot create /sys/kernel/debug/vgaswitcheroo\n"); 443 goto fail; 444 } 445 446 priv->switch_file = debugfs_create_file("switch", 0644, 447 priv->debugfs_root, NULL, &vga_switcheroo_debugfs_fops); 448 if (!priv->switch_file) { 449 printk(KERN_ERR "vga_switcheroo: cannot create /sys/kernel/debug/vgaswitcheroo/switch\n"); 450 goto fail; 451 } 452 return 0; 453 fail: 454 vga_switcheroo_debugfs_fini(priv); 455 return -1; 456 } 457 458 int vga_switcheroo_process_delayed_switch(void) 459 { 460 struct vga_switcheroo_client *client = NULL; 461 const char *pdev_name; 462 bool can_switch = true; 463 int i; 464 int ret; 465 int err = -EINVAL; 466 467 mutex_lock(&vgasr_mutex); 468 if (!vgasr_priv.delayed_switch_active) 469 goto err; 470 471 printk(KERN_INFO "vga_switcheroo: processing delayed switch to %d\n", vgasr_priv.delayed_client_id); 472 473 for (i = 0; i < VGA_SWITCHEROO_MAX_CLIENTS; i++) { 474 if (vgasr_priv.clients[i].id == vgasr_priv.delayed_client_id) 475 client = &vgasr_priv.clients[i]; 476 can_switch = vgasr_priv.clients[i].can_switch(vgasr_priv.clients[i].pdev); 477 if (can_switch == false) { 478 printk(KERN_ERR "vga_switcheroo: client %d refused switch\n", i); 479 break; 480 } 481 } 482 483 if (can_switch == false || client == NULL) 484 goto err; 485 486 pdev_name = pci_name(client->pdev); 487 ret = vga_switchto_stage2(client); 488 if (ret) 489 printk(KERN_ERR "vga_switcheroo: delayed switching failed stage 2 %d\n", ret); 490 491 vgasr_priv.delayed_switch_active = false; 492 err = 0; 493 err: 494 mutex_unlock(&vgasr_mutex); 495 return err; 496 } 497 EXPORT_SYMBOL(vga_switcheroo_process_delayed_switch); 498 499