vga_switcheroo.c 13 KB

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