vga_switcheroo.c 12 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498
  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. Switcher interface - methods require for ATPX and DCM
  10. - switchto - this throws the output MUX switch
  11. - discrete_set_power - sets the power state for the discrete card
  12. GPU driver interface
  13. - set_gpu_state - this should do the equiv of s/r for the card
  14. - this should *not* set the discrete power state
  15. - switch_check - check if the device is in a position to switch now
  16. */
  17. #include <linux/module.h>
  18. #include <linux/dmi.h>
  19. #include <linux/seq_file.h>
  20. #include <linux/uaccess.h>
  21. #include <linux/fs.h>
  22. #include <linux/debugfs.h>
  23. #include <linux/fb.h>
  24. #include <linux/pci.h>
  25. #include <linux/vga_switcheroo.h>
  26. #include <linux/vgaarb.h>
  27. struct vga_switcheroo_client {
  28. struct pci_dev *pdev;
  29. struct fb_info *fb_info;
  30. int pwr_state;
  31. const struct vga_switcheroo_client_ops *ops;
  32. int id;
  33. bool active;
  34. struct list_head list;
  35. };
  36. static DEFINE_MUTEX(vgasr_mutex);
  37. struct vgasr_priv {
  38. bool active;
  39. bool delayed_switch_active;
  40. enum vga_switcheroo_client_id delayed_client_id;
  41. struct dentry *debugfs_root;
  42. struct dentry *switch_file;
  43. int registered_clients;
  44. struct list_head clients;
  45. struct vga_switcheroo_handler *handler;
  46. };
  47. static int vga_switcheroo_debugfs_init(struct vgasr_priv *priv);
  48. static void vga_switcheroo_debugfs_fini(struct vgasr_priv *priv);
  49. /* only one switcheroo per system */
  50. static struct vgasr_priv vgasr_priv = {
  51. .clients = LIST_HEAD_INIT(vgasr_priv.clients),
  52. };
  53. int vga_switcheroo_register_handler(struct vga_switcheroo_handler *handler)
  54. {
  55. mutex_lock(&vgasr_mutex);
  56. if (vgasr_priv.handler) {
  57. mutex_unlock(&vgasr_mutex);
  58. return -EINVAL;
  59. }
  60. vgasr_priv.handler = handler;
  61. mutex_unlock(&vgasr_mutex);
  62. return 0;
  63. }
  64. EXPORT_SYMBOL(vga_switcheroo_register_handler);
  65. void vga_switcheroo_unregister_handler(void)
  66. {
  67. mutex_lock(&vgasr_mutex);
  68. vgasr_priv.handler = NULL;
  69. mutex_unlock(&vgasr_mutex);
  70. }
  71. EXPORT_SYMBOL(vga_switcheroo_unregister_handler);
  72. static void vga_switcheroo_enable(void)
  73. {
  74. int ret;
  75. struct vga_switcheroo_client *client;
  76. /* call the handler to init */
  77. vgasr_priv.handler->init();
  78. list_for_each_entry(client, &vgasr_priv.clients, list) {
  79. ret = vgasr_priv.handler->get_client_id(client->pdev);
  80. if (ret < 0)
  81. return;
  82. client->id = ret;
  83. }
  84. vga_switcheroo_debugfs_init(&vgasr_priv);
  85. vgasr_priv.active = true;
  86. }
  87. int vga_switcheroo_register_client(struct pci_dev *pdev,
  88. const struct vga_switcheroo_client_ops *ops)
  89. {
  90. struct vga_switcheroo_client *client;
  91. client = kzalloc(sizeof(*client), GFP_KERNEL);
  92. if (!client)
  93. return -ENOMEM;
  94. client->pwr_state = VGA_SWITCHEROO_ON;
  95. client->pdev = pdev;
  96. client->ops = ops;
  97. client->id = -1;
  98. if (pdev == vga_default_device())
  99. client->active = true;
  100. mutex_lock(&vgasr_mutex);
  101. list_add_tail(&client->list, &vgasr_priv.clients);
  102. vgasr_priv.registered_clients++;
  103. /* if we get two clients + handler */
  104. if (vgasr_priv.registered_clients == 2 && vgasr_priv.handler) {
  105. printk(KERN_INFO "vga_switcheroo: enabled\n");
  106. vga_switcheroo_enable();
  107. }
  108. mutex_unlock(&vgasr_mutex);
  109. return 0;
  110. }
  111. EXPORT_SYMBOL(vga_switcheroo_register_client);
  112. static struct vga_switcheroo_client *
  113. find_client_from_pci(struct list_head *head, struct pci_dev *pdev)
  114. {
  115. struct vga_switcheroo_client *client;
  116. list_for_each_entry(client, head, list)
  117. if (client->pdev == pdev)
  118. return client;
  119. return NULL;
  120. }
  121. static struct vga_switcheroo_client *
  122. find_client_from_id(struct list_head *head, int client_id)
  123. {
  124. struct vga_switcheroo_client *client;
  125. list_for_each_entry(client, head, list)
  126. if (client->id == client_id)
  127. return client;
  128. return NULL;
  129. }
  130. static struct vga_switcheroo_client *
  131. find_active_client(struct list_head *head)
  132. {
  133. struct vga_switcheroo_client *client;
  134. list_for_each_entry(client, head, list)
  135. if (client->active == true)
  136. return client;
  137. return NULL;
  138. }
  139. void vga_switcheroo_unregister_client(struct pci_dev *pdev)
  140. {
  141. struct vga_switcheroo_client *client;
  142. mutex_lock(&vgasr_mutex);
  143. client = find_client_from_pci(&vgasr_priv.clients, pdev);
  144. if (client) {
  145. list_del(&client->list);
  146. kfree(client);
  147. vgasr_priv.registered_clients--;
  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. void vga_switcheroo_client_fb_set(struct pci_dev *pdev,
  156. struct fb_info *info)
  157. {
  158. struct vga_switcheroo_client *client;
  159. mutex_lock(&vgasr_mutex);
  160. client = find_client_from_pci(&vgasr_priv.clients, pdev);
  161. if (client)
  162. client->fb_info = info;
  163. mutex_unlock(&vgasr_mutex);
  164. }
  165. EXPORT_SYMBOL(vga_switcheroo_client_fb_set);
  166. static int vga_switcheroo_show(struct seq_file *m, void *v)
  167. {
  168. struct vga_switcheroo_client *client;
  169. int i = 0;
  170. mutex_lock(&vgasr_mutex);
  171. list_for_each_entry(client, &vgasr_priv.clients, list) {
  172. seq_printf(m, "%d:%s:%c:%s:%s\n", i,
  173. client->id == VGA_SWITCHEROO_DIS ? "DIS" : "IGD",
  174. client->active ? '+' : ' ',
  175. client->pwr_state ? "Pwr" : "Off",
  176. pci_name(client->pdev));
  177. i++;
  178. }
  179. mutex_unlock(&vgasr_mutex);
  180. return 0;
  181. }
  182. static int vga_switcheroo_debugfs_open(struct inode *inode, struct file *file)
  183. {
  184. return single_open(file, vga_switcheroo_show, NULL);
  185. }
  186. static int vga_switchon(struct vga_switcheroo_client *client)
  187. {
  188. if (vgasr_priv.handler->power_state)
  189. vgasr_priv.handler->power_state(client->id, VGA_SWITCHEROO_ON);
  190. /* call the driver callback to turn on device */
  191. client->ops->set_gpu_state(client->pdev, VGA_SWITCHEROO_ON);
  192. client->pwr_state = VGA_SWITCHEROO_ON;
  193. return 0;
  194. }
  195. static int vga_switchoff(struct vga_switcheroo_client *client)
  196. {
  197. /* call the driver callback to turn off device */
  198. client->ops->set_gpu_state(client->pdev, VGA_SWITCHEROO_OFF);
  199. if (vgasr_priv.handler->power_state)
  200. vgasr_priv.handler->power_state(client->id, VGA_SWITCHEROO_OFF);
  201. client->pwr_state = VGA_SWITCHEROO_OFF;
  202. return 0;
  203. }
  204. /* stage one happens before delay */
  205. static int vga_switchto_stage1(struct vga_switcheroo_client *new_client)
  206. {
  207. struct vga_switcheroo_client *active;
  208. active = find_active_client(&vgasr_priv.clients);
  209. if (!active)
  210. return 0;
  211. if (new_client->pwr_state == VGA_SWITCHEROO_OFF)
  212. vga_switchon(new_client);
  213. vga_set_default_device(new_client->pdev);
  214. return 0;
  215. }
  216. /* post delay */
  217. static int vga_switchto_stage2(struct vga_switcheroo_client *new_client)
  218. {
  219. int ret;
  220. struct vga_switcheroo_client *active;
  221. active = find_active_client(&vgasr_priv.clients);
  222. if (!active)
  223. return 0;
  224. active->active = false;
  225. if (new_client->fb_info) {
  226. struct fb_event event;
  227. event.info = new_client->fb_info;
  228. fb_notifier_call_chain(FB_EVENT_REMAP_ALL_CONSOLE, &event);
  229. }
  230. ret = vgasr_priv.handler->switchto(new_client->id);
  231. if (ret)
  232. return ret;
  233. if (new_client->ops->reprobe)
  234. new_client->ops->reprobe(new_client->pdev);
  235. if (active->pwr_state == VGA_SWITCHEROO_ON)
  236. vga_switchoff(active);
  237. new_client->active = true;
  238. return 0;
  239. }
  240. static bool check_can_switch(void)
  241. {
  242. struct vga_switcheroo_client *client;
  243. list_for_each_entry(client, &vgasr_priv.clients, list) {
  244. if (!client->ops->can_switch(client->pdev)) {
  245. printk(KERN_ERR "vga_switcheroo: client %x refused switch\n", client->id);
  246. return false;
  247. }
  248. }
  249. return true;
  250. }
  251. static ssize_t
  252. vga_switcheroo_debugfs_write(struct file *filp, const char __user *ubuf,
  253. size_t cnt, loff_t *ppos)
  254. {
  255. char usercmd[64];
  256. const char *pdev_name;
  257. int ret;
  258. bool delay = false, can_switch;
  259. bool just_mux = false;
  260. int client_id = -1;
  261. struct vga_switcheroo_client *client = NULL;
  262. if (cnt > 63)
  263. cnt = 63;
  264. if (copy_from_user(usercmd, ubuf, cnt))
  265. return -EFAULT;
  266. mutex_lock(&vgasr_mutex);
  267. if (!vgasr_priv.active) {
  268. cnt = -EINVAL;
  269. goto out;
  270. }
  271. /* pwr off the device not in use */
  272. if (strncmp(usercmd, "OFF", 3) == 0) {
  273. list_for_each_entry(client, &vgasr_priv.clients, list) {
  274. if (client->active)
  275. continue;
  276. if (client->pwr_state == VGA_SWITCHEROO_ON)
  277. vga_switchoff(client);
  278. }
  279. goto out;
  280. }
  281. /* pwr on the device not in use */
  282. if (strncmp(usercmd, "ON", 2) == 0) {
  283. list_for_each_entry(client, &vgasr_priv.clients, list) {
  284. if (client->active)
  285. continue;
  286. if (client->pwr_state == VGA_SWITCHEROO_OFF)
  287. vga_switchon(client);
  288. }
  289. goto out;
  290. }
  291. /* request a delayed switch - test can we switch now */
  292. if (strncmp(usercmd, "DIGD", 4) == 0) {
  293. client_id = VGA_SWITCHEROO_IGD;
  294. delay = true;
  295. }
  296. if (strncmp(usercmd, "DDIS", 4) == 0) {
  297. client_id = VGA_SWITCHEROO_DIS;
  298. delay = true;
  299. }
  300. if (strncmp(usercmd, "IGD", 3) == 0)
  301. client_id = VGA_SWITCHEROO_IGD;
  302. if (strncmp(usercmd, "DIS", 3) == 0)
  303. client_id = VGA_SWITCHEROO_DIS;
  304. if (strncmp(usercmd, "MIGD", 4) == 0) {
  305. just_mux = true;
  306. client_id = VGA_SWITCHEROO_IGD;
  307. }
  308. if (strncmp(usercmd, "MDIS", 4) == 0) {
  309. just_mux = true;
  310. client_id = VGA_SWITCHEROO_DIS;
  311. }
  312. if (client_id == -1)
  313. goto out;
  314. client = find_client_from_id(&vgasr_priv.clients, client_id);
  315. if (!client)
  316. goto out;
  317. vgasr_priv.delayed_switch_active = false;
  318. if (just_mux) {
  319. ret = vgasr_priv.handler->switchto(client_id);
  320. goto out;
  321. }
  322. if (client->active)
  323. goto out;
  324. /* okay we want a switch - test if devices are willing to switch */
  325. can_switch = check_can_switch();
  326. if (can_switch == false && delay == false)
  327. goto out;
  328. if (can_switch) {
  329. pdev_name = pci_name(client->pdev);
  330. ret = vga_switchto_stage1(client);
  331. if (ret)
  332. printk(KERN_ERR "vga_switcheroo: switching failed stage 1 %d\n", ret);
  333. ret = vga_switchto_stage2(client);
  334. if (ret)
  335. printk(KERN_ERR "vga_switcheroo: switching failed stage 2 %d\n", ret);
  336. } else {
  337. printk(KERN_INFO "vga_switcheroo: setting delayed switch to client %d\n", client->id);
  338. vgasr_priv.delayed_switch_active = true;
  339. vgasr_priv.delayed_client_id = client_id;
  340. ret = vga_switchto_stage1(client);
  341. if (ret)
  342. printk(KERN_ERR "vga_switcheroo: delayed switching stage 1 failed %d\n", ret);
  343. }
  344. out:
  345. mutex_unlock(&vgasr_mutex);
  346. return cnt;
  347. }
  348. static const struct file_operations vga_switcheroo_debugfs_fops = {
  349. .owner = THIS_MODULE,
  350. .open = vga_switcheroo_debugfs_open,
  351. .write = vga_switcheroo_debugfs_write,
  352. .read = seq_read,
  353. .llseek = seq_lseek,
  354. .release = single_release,
  355. };
  356. static void vga_switcheroo_debugfs_fini(struct vgasr_priv *priv)
  357. {
  358. if (priv->switch_file) {
  359. debugfs_remove(priv->switch_file);
  360. priv->switch_file = NULL;
  361. }
  362. if (priv->debugfs_root) {
  363. debugfs_remove(priv->debugfs_root);
  364. priv->debugfs_root = NULL;
  365. }
  366. }
  367. static int vga_switcheroo_debugfs_init(struct vgasr_priv *priv)
  368. {
  369. /* already initialised */
  370. if (priv->debugfs_root)
  371. return 0;
  372. priv->debugfs_root = debugfs_create_dir("vgaswitcheroo", NULL);
  373. if (!priv->debugfs_root) {
  374. printk(KERN_ERR "vga_switcheroo: Cannot create /sys/kernel/debug/vgaswitcheroo\n");
  375. goto fail;
  376. }
  377. priv->switch_file = debugfs_create_file("switch", 0644,
  378. priv->debugfs_root, NULL, &vga_switcheroo_debugfs_fops);
  379. if (!priv->switch_file) {
  380. printk(KERN_ERR "vga_switcheroo: cannot create /sys/kernel/debug/vgaswitcheroo/switch\n");
  381. goto fail;
  382. }
  383. return 0;
  384. fail:
  385. vga_switcheroo_debugfs_fini(priv);
  386. return -1;
  387. }
  388. int vga_switcheroo_process_delayed_switch(void)
  389. {
  390. struct vga_switcheroo_client *client;
  391. const char *pdev_name;
  392. int ret;
  393. int err = -EINVAL;
  394. mutex_lock(&vgasr_mutex);
  395. if (!vgasr_priv.delayed_switch_active)
  396. goto err;
  397. printk(KERN_INFO "vga_switcheroo: processing delayed switch to %d\n", vgasr_priv.delayed_client_id);
  398. client = find_client_from_id(&vgasr_priv.clients,
  399. vgasr_priv.delayed_client_id);
  400. if (!client || !check_can_switch())
  401. goto err;
  402. pdev_name = pci_name(client->pdev);
  403. ret = vga_switchto_stage2(client);
  404. if (ret)
  405. printk(KERN_ERR "vga_switcheroo: delayed switching failed stage 2 %d\n", ret);
  406. vgasr_priv.delayed_switch_active = false;
  407. err = 0;
  408. err:
  409. mutex_unlock(&vgasr_mutex);
  410. return err;
  411. }
  412. EXPORT_SYMBOL(vga_switcheroo_process_delayed_switch);