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 i; 219 struct vga_switcheroo_client *active = NULL; 220 221 for (i = 0; i < VGA_SWITCHEROO_MAX_CLIENTS; i++) { 222 if (vgasr_priv.clients[i].active == true) { 223 active = &vgasr_priv.clients[i]; 224 break; 225 } 226 } 227 if (!active) 228 return 0; 229 230 if (new_client->pwr_state == VGA_SWITCHEROO_OFF) 231 vga_switchon(new_client); 232 233 /* swap shadow resource to denote boot VGA device has changed so X starts on new device */ 234 active->pdev->resource[PCI_ROM_RESOURCE].flags &= ~IORESOURCE_ROM_SHADOW; 235 new_client->pdev->resource[PCI_ROM_RESOURCE].flags |= IORESOURCE_ROM_SHADOW; 236 return 0; 237 } 238 239 /* post delay */ 240 static int vga_switchto_stage2(struct vga_switcheroo_client *new_client) 241 { 242 int ret; 243 int i; 244 struct vga_switcheroo_client *active = NULL; 245 246 for (i = 0; i < VGA_SWITCHEROO_MAX_CLIENTS; i++) { 247 if (vgasr_priv.clients[i].active == true) { 248 active = &vgasr_priv.clients[i]; 249 break; 250 } 251 } 252 if (!active) 253 return 0; 254 255 active->active = false; 256 257 if (new_client->fb_info) { 258 struct fb_event event; 259 event.info = new_client->fb_info; 260 fb_notifier_call_chain(FB_EVENT_REMAP_ALL_CONSOLE, &event); 261 } 262 263 ret = vgasr_priv.handler->switchto(new_client->id); 264 if (ret) 265 return ret; 266 267 if (new_client->reprobe) 268 new_client->reprobe(new_client->pdev); 269 270 if (active->pwr_state == VGA_SWITCHEROO_ON) 271 vga_switchoff(active); 272 273 new_client->active = true; 274 return 0; 275 } 276 277 static ssize_t 278 vga_switcheroo_debugfs_write(struct file *filp, const char __user *ubuf, 279 size_t cnt, loff_t *ppos) 280 { 281 char usercmd[64]; 282 const char *pdev_name; 283 int i, ret; 284 bool delay = false, can_switch; 285 bool just_mux = false; 286 int client_id = -1; 287 struct vga_switcheroo_client *client = NULL; 288 289 if (cnt > 63) 290 cnt = 63; 291 292 if (copy_from_user(usercmd, ubuf, cnt)) 293 return -EFAULT; 294 295 mutex_lock(&vgasr_mutex); 296 297 if (!vgasr_priv.active) { 298 cnt = -EINVAL; 299 goto out; 300 } 301 302 /* pwr off the device not in use */ 303 if (strncmp(usercmd, "OFF", 3) == 0) { 304 for (i = 0; i < VGA_SWITCHEROO_MAX_CLIENTS; i++) { 305 if (vgasr_priv.clients[i].active) 306 continue; 307 if (vgasr_priv.clients[i].pwr_state == VGA_SWITCHEROO_ON) 308 vga_switchoff(&vgasr_priv.clients[i]); 309 } 310 goto out; 311 } 312 /* pwr on the device not in use */ 313 if (strncmp(usercmd, "ON", 2) == 0) { 314 for (i = 0; i < VGA_SWITCHEROO_MAX_CLIENTS; i++) { 315 if (vgasr_priv.clients[i].active) 316 continue; 317 if (vgasr_priv.clients[i].pwr_state == VGA_SWITCHEROO_OFF) 318 vga_switchon(&vgasr_priv.clients[i]); 319 } 320 goto out; 321 } 322 323 /* request a delayed switch - test can we switch now */ 324 if (strncmp(usercmd, "DIGD", 4) == 0) { 325 client_id = VGA_SWITCHEROO_IGD; 326 delay = true; 327 } 328 329 if (strncmp(usercmd, "DDIS", 4) == 0) { 330 client_id = VGA_SWITCHEROO_DIS; 331 delay = true; 332 } 333 334 if (strncmp(usercmd, "IGD", 3) == 0) 335 client_id = VGA_SWITCHEROO_IGD; 336 337 if (strncmp(usercmd, "DIS", 3) == 0) 338 client_id = VGA_SWITCHEROO_DIS; 339 340 if (strncmp(usercmd, "MIGD", 4) == 0) { 341 just_mux = true; 342 client_id = VGA_SWITCHEROO_IGD; 343 } 344 if (strncmp(usercmd, "MDIS", 4) == 0) { 345 just_mux = true; 346 client_id = VGA_SWITCHEROO_DIS; 347 } 348 349 if (client_id == -1) 350 goto out; 351 352 for (i = 0; i < VGA_SWITCHEROO_MAX_CLIENTS; i++) { 353 if (vgasr_priv.clients[i].id == client_id) { 354 client = &vgasr_priv.clients[i]; 355 break; 356 } 357 } 358 359 vgasr_priv.delayed_switch_active = false; 360 361 if (just_mux) { 362 ret = vgasr_priv.handler->switchto(client_id); 363 goto out; 364 } 365 366 if (client->active == true) 367 goto out; 368 369 /* okay we want a switch - test if devices are willing to switch */ 370 can_switch = true; 371 for (i = 0; i < VGA_SWITCHEROO_MAX_CLIENTS; i++) { 372 can_switch = vgasr_priv.clients[i].can_switch(vgasr_priv.clients[i].pdev); 373 if (can_switch == false) { 374 printk(KERN_ERR "vga_switcheroo: client %d refused switch\n", i); 375 break; 376 } 377 } 378 379 if (can_switch == false && delay == false) 380 goto out; 381 382 if (can_switch == true) { 383 pdev_name = pci_name(client->pdev); 384 ret = vga_switchto_stage1(client); 385 if (ret) 386 printk(KERN_ERR "vga_switcheroo: switching failed stage 1 %d\n", ret); 387 388 ret = vga_switchto_stage2(client); 389 if (ret) 390 printk(KERN_ERR "vga_switcheroo: switching failed stage 2 %d\n", ret); 391 392 } else { 393 printk(KERN_INFO "vga_switcheroo: setting delayed switch to client %d\n", client->id); 394 vgasr_priv.delayed_switch_active = true; 395 vgasr_priv.delayed_client_id = client_id; 396 397 ret = vga_switchto_stage1(client); 398 if (ret) 399 printk(KERN_ERR "vga_switcheroo: delayed switching stage 1 failed %d\n", ret); 400 } 401 402 out: 403 mutex_unlock(&vgasr_mutex); 404 return cnt; 405 } 406 407 static const struct file_operations vga_switcheroo_debugfs_fops = { 408 .owner = THIS_MODULE, 409 .open = vga_switcheroo_debugfs_open, 410 .write = vga_switcheroo_debugfs_write, 411 .read = seq_read, 412 .llseek = seq_lseek, 413 .release = single_release, 414 }; 415 416 static void vga_switcheroo_debugfs_fini(struct vgasr_priv *priv) 417 { 418 if (priv->switch_file) { 419 debugfs_remove(priv->switch_file); 420 priv->switch_file = NULL; 421 } 422 if (priv->debugfs_root) { 423 debugfs_remove(priv->debugfs_root); 424 priv->debugfs_root = NULL; 425 } 426 } 427 428 static int vga_switcheroo_debugfs_init(struct vgasr_priv *priv) 429 { 430 /* already initialised */ 431 if (priv->debugfs_root) 432 return 0; 433 priv->debugfs_root = debugfs_create_dir("vgaswitcheroo", NULL); 434 435 if (!priv->debugfs_root) { 436 printk(KERN_ERR "vga_switcheroo: Cannot create /sys/kernel/debug/vgaswitcheroo\n"); 437 goto fail; 438 } 439 440 priv->switch_file = debugfs_create_file("switch", 0644, 441 priv->debugfs_root, NULL, &vga_switcheroo_debugfs_fops); 442 if (!priv->switch_file) { 443 printk(KERN_ERR "vga_switcheroo: cannot create /sys/kernel/debug/vgaswitcheroo/switch\n"); 444 goto fail; 445 } 446 return 0; 447 fail: 448 vga_switcheroo_debugfs_fini(priv); 449 return -1; 450 } 451 452 int vga_switcheroo_process_delayed_switch(void) 453 { 454 struct vga_switcheroo_client *client = NULL; 455 const char *pdev_name; 456 bool can_switch = true; 457 int i; 458 int ret; 459 int err = -EINVAL; 460 461 mutex_lock(&vgasr_mutex); 462 if (!vgasr_priv.delayed_switch_active) 463 goto err; 464 465 printk(KERN_INFO "vga_switcheroo: processing delayed switch to %d\n", vgasr_priv.delayed_client_id); 466 467 for (i = 0; i < VGA_SWITCHEROO_MAX_CLIENTS; i++) { 468 if (vgasr_priv.clients[i].id == vgasr_priv.delayed_client_id) 469 client = &vgasr_priv.clients[i]; 470 can_switch = vgasr_priv.clients[i].can_switch(vgasr_priv.clients[i].pdev); 471 if (can_switch == false) { 472 printk(KERN_ERR "vga_switcheroo: client %d refused switch\n", i); 473 break; 474 } 475 } 476 477 if (can_switch == false || client == NULL) 478 goto err; 479 480 pdev_name = pci_name(client->pdev); 481 ret = vga_switchto_stage2(client); 482 if (ret) 483 printk(KERN_ERR "vga_switcheroo: delayed switching failed stage 2 %d\n", ret); 484 485 vgasr_priv.delayed_switch_active = false; 486 err = 0; 487 err: 488 mutex_unlock(&vgasr_mutex); 489 return err; 490 } 491 EXPORT_SYMBOL(vga_switcheroo_process_delayed_switch); 492 493