vga_switcheroo.c 14 KB

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