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