xref: /openbmc/linux/drivers/gpu/vga/vga_switcheroo.c (revision baa7eb025ab14f3cba2e35c0a8648f9c9f01d24f)
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