video_detect.c 23 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665666667668669670671672673674675676677678679680681682683684685686687688689690691692693694695696697698699700701702703704705706707708709710711712713714715716717718719720721722723724725726727728729730731732733734735736737738739740741742743744745746747748749750751752753754755756757758759760761762763764765766767768769770771772773774775776777778779780781782783784785786787788789790791792793794795796797798799800801802803804805806807808809810811812813814815816817818819820821822823824825826827828829830831832833834835836837838839840841842843844845846847848849850851852853854855856857858859860861862863864865866867868869870871872873874875
  1. /*
  2. * Copyright (C) 2015 Red Hat Inc.
  3. * Hans de Goede <[email protected]>
  4. * Copyright (C) 2008 SuSE Linux Products GmbH
  5. * Thomas Renninger <[email protected]>
  6. *
  7. * May be copied or modified under the terms of the GNU General Public License
  8. *
  9. * video_detect.c:
  10. * After PCI devices are glued with ACPI devices
  11. * acpi_get_pci_dev() can be called to identify ACPI graphics
  12. * devices for which a real graphics card is plugged in
  13. *
  14. * Depending on whether ACPI graphics extensions (cmp. ACPI spec Appendix B)
  15. * are available, video.ko should be used to handle the device.
  16. *
  17. * Otherwise vendor specific drivers like thinkpad_acpi, asus-laptop,
  18. * sony_acpi,... can take care about backlight brightness.
  19. *
  20. * Backlight drivers can use acpi_video_get_backlight_type() to determine which
  21. * driver should handle the backlight. RAW/GPU-driver backlight drivers must
  22. * use the acpi_video_backlight_use_native() helper for this.
  23. *
  24. * If CONFIG_ACPI_VIDEO is neither set as "compiled in" (y) nor as a module (m)
  25. * this file will not be compiled and acpi_video_get_backlight_type() will
  26. * always return acpi_backlight_vendor.
  27. */
  28. #include <linux/export.h>
  29. #include <linux/acpi.h>
  30. #include <linux/apple-gmux.h>
  31. #include <linux/backlight.h>
  32. #include <linux/dmi.h>
  33. #include <linux/module.h>
  34. #include <linux/pci.h>
  35. #include <linux/platform_data/x86/nvidia-wmi-ec-backlight.h>
  36. #include <linux/pnp.h>
  37. #include <linux/types.h>
  38. #include <linux/workqueue.h>
  39. #include <acpi/video.h>
  40. static enum acpi_backlight_type acpi_backlight_cmdline = acpi_backlight_undef;
  41. static enum acpi_backlight_type acpi_backlight_dmi = acpi_backlight_undef;
  42. static void acpi_video_parse_cmdline(void)
  43. {
  44. if (!strcmp("vendor", acpi_video_backlight_string))
  45. acpi_backlight_cmdline = acpi_backlight_vendor;
  46. if (!strcmp("video", acpi_video_backlight_string))
  47. acpi_backlight_cmdline = acpi_backlight_video;
  48. if (!strcmp("native", acpi_video_backlight_string))
  49. acpi_backlight_cmdline = acpi_backlight_native;
  50. if (!strcmp("nvidia_wmi_ec", acpi_video_backlight_string))
  51. acpi_backlight_cmdline = acpi_backlight_nvidia_wmi_ec;
  52. if (!strcmp("apple_gmux", acpi_video_backlight_string))
  53. acpi_backlight_cmdline = acpi_backlight_apple_gmux;
  54. if (!strcmp("none", acpi_video_backlight_string))
  55. acpi_backlight_cmdline = acpi_backlight_none;
  56. }
  57. static acpi_status
  58. find_video(acpi_handle handle, u32 lvl, void *context, void **rv)
  59. {
  60. struct acpi_device *acpi_dev = acpi_fetch_acpi_dev(handle);
  61. long *cap = context;
  62. struct pci_dev *dev;
  63. static const struct acpi_device_id video_ids[] = {
  64. {ACPI_VIDEO_HID, 0},
  65. {"", 0},
  66. };
  67. if (acpi_dev && !acpi_match_device_ids(acpi_dev, video_ids)) {
  68. dev = acpi_get_pci_dev(handle);
  69. if (!dev)
  70. return AE_OK;
  71. pci_dev_put(dev);
  72. *cap |= acpi_is_video_device(handle);
  73. }
  74. return AE_OK;
  75. }
  76. /* This depends on ACPI_WMI which is X86 only */
  77. #ifdef CONFIG_X86
  78. static bool nvidia_wmi_ec_supported(void)
  79. {
  80. struct wmi_brightness_args args = {
  81. .mode = WMI_BRIGHTNESS_MODE_GET,
  82. .val = 0,
  83. .ret = 0,
  84. };
  85. struct acpi_buffer buf = { (acpi_size)sizeof(args), &args };
  86. acpi_status status;
  87. status = wmi_evaluate_method(WMI_BRIGHTNESS_GUID, 0,
  88. WMI_BRIGHTNESS_METHOD_SOURCE, &buf, &buf);
  89. if (ACPI_FAILURE(status))
  90. return false;
  91. /*
  92. * If brightness is handled by the EC then nvidia-wmi-ec-backlight
  93. * should be used, else the GPU driver(s) should be used.
  94. */
  95. return args.ret == WMI_BRIGHTNESS_SOURCE_EC;
  96. }
  97. #else
  98. static bool nvidia_wmi_ec_supported(void)
  99. {
  100. return false;
  101. }
  102. #endif
  103. /* Force to use vendor driver when the ACPI device is known to be
  104. * buggy */
  105. static int video_detect_force_vendor(const struct dmi_system_id *d)
  106. {
  107. acpi_backlight_dmi = acpi_backlight_vendor;
  108. return 0;
  109. }
  110. static int video_detect_force_video(const struct dmi_system_id *d)
  111. {
  112. acpi_backlight_dmi = acpi_backlight_video;
  113. return 0;
  114. }
  115. static int video_detect_force_native(const struct dmi_system_id *d)
  116. {
  117. acpi_backlight_dmi = acpi_backlight_native;
  118. return 0;
  119. }
  120. static int video_detect_portege_r100(const struct dmi_system_id *d)
  121. {
  122. struct pci_dev *dev;
  123. /* Search for Trident CyberBlade XP4m32 to confirm Portégé R100 */
  124. dev = pci_get_device(PCI_VENDOR_ID_TRIDENT, 0x2100, NULL);
  125. if (dev)
  126. acpi_backlight_dmi = acpi_backlight_vendor;
  127. return 0;
  128. }
  129. static const struct dmi_system_id video_detect_dmi_table[] = {
  130. /*
  131. * Models which should use the vendor backlight interface,
  132. * because of broken ACPI video backlight control.
  133. */
  134. {
  135. /* https://bugzilla.redhat.com/show_bug.cgi?id=1128309 */
  136. .callback = video_detect_force_vendor,
  137. /* Acer KAV80 */
  138. .matches = {
  139. DMI_MATCH(DMI_SYS_VENDOR, "Acer"),
  140. DMI_MATCH(DMI_PRODUCT_NAME, "KAV80"),
  141. },
  142. },
  143. {
  144. .callback = video_detect_force_vendor,
  145. /* Asus UL30VT */
  146. .matches = {
  147. DMI_MATCH(DMI_SYS_VENDOR, "ASUSTeK Computer Inc."),
  148. DMI_MATCH(DMI_PRODUCT_NAME, "UL30VT"),
  149. },
  150. },
  151. {
  152. .callback = video_detect_force_vendor,
  153. /* Asus UL30A */
  154. .matches = {
  155. DMI_MATCH(DMI_SYS_VENDOR, "ASUSTeK Computer Inc."),
  156. DMI_MATCH(DMI_PRODUCT_NAME, "UL30A"),
  157. },
  158. },
  159. {
  160. .callback = video_detect_force_vendor,
  161. /* Asus X55U */
  162. .matches = {
  163. DMI_MATCH(DMI_SYS_VENDOR, "ASUSTeK COMPUTER INC."),
  164. DMI_MATCH(DMI_PRODUCT_NAME, "X55U"),
  165. },
  166. },
  167. {
  168. .callback = video_detect_force_vendor,
  169. /* Asus X101CH */
  170. .matches = {
  171. DMI_MATCH(DMI_SYS_VENDOR, "ASUSTeK COMPUTER INC."),
  172. DMI_MATCH(DMI_PRODUCT_NAME, "X101CH"),
  173. },
  174. },
  175. {
  176. .callback = video_detect_force_vendor,
  177. /* Asus X401U */
  178. .matches = {
  179. DMI_MATCH(DMI_SYS_VENDOR, "ASUSTeK COMPUTER INC."),
  180. DMI_MATCH(DMI_PRODUCT_NAME, "X401U"),
  181. },
  182. },
  183. {
  184. .callback = video_detect_force_vendor,
  185. /* Asus X501U */
  186. .matches = {
  187. DMI_MATCH(DMI_SYS_VENDOR, "ASUSTeK COMPUTER INC."),
  188. DMI_MATCH(DMI_PRODUCT_NAME, "X501U"),
  189. },
  190. },
  191. {
  192. .callback = video_detect_force_vendor,
  193. /* Asus 1015CX */
  194. .matches = {
  195. DMI_MATCH(DMI_SYS_VENDOR, "ASUSTeK COMPUTER INC."),
  196. DMI_MATCH(DMI_PRODUCT_NAME, "1015CX"),
  197. },
  198. },
  199. {
  200. .callback = video_detect_force_vendor,
  201. /* Samsung N150/N210/N220 */
  202. .matches = {
  203. DMI_MATCH(DMI_SYS_VENDOR, "SAMSUNG ELECTRONICS CO., LTD."),
  204. DMI_MATCH(DMI_PRODUCT_NAME, "N150/N210/N220"),
  205. DMI_MATCH(DMI_BOARD_NAME, "N150/N210/N220"),
  206. },
  207. },
  208. {
  209. .callback = video_detect_force_vendor,
  210. /* Samsung NF110/NF210/NF310 */
  211. .matches = {
  212. DMI_MATCH(DMI_SYS_VENDOR, "SAMSUNG ELECTRONICS CO., LTD."),
  213. DMI_MATCH(DMI_PRODUCT_NAME, "NF110/NF210/NF310"),
  214. DMI_MATCH(DMI_BOARD_NAME, "NF110/NF210/NF310"),
  215. },
  216. },
  217. {
  218. .callback = video_detect_force_vendor,
  219. /* Samsung NC210 */
  220. .matches = {
  221. DMI_MATCH(DMI_SYS_VENDOR, "SAMSUNG ELECTRONICS CO., LTD."),
  222. DMI_MATCH(DMI_PRODUCT_NAME, "NC210/NC110"),
  223. DMI_MATCH(DMI_BOARD_NAME, "NC210/NC110"),
  224. },
  225. },
  226. {
  227. .callback = video_detect_force_vendor,
  228. /* Xiaomi Mi Pad 2 */
  229. .matches = {
  230. DMI_MATCH(DMI_SYS_VENDOR, "Xiaomi Inc"),
  231. DMI_MATCH(DMI_PRODUCT_NAME, "Mipad2"),
  232. },
  233. },
  234. /*
  235. * Models which should use the vendor backlight interface,
  236. * because of broken native backlight control.
  237. */
  238. {
  239. .callback = video_detect_force_vendor,
  240. /* Sony Vaio PCG-FRV35 */
  241. .matches = {
  242. DMI_MATCH(DMI_SYS_VENDOR, "Sony Corporation"),
  243. DMI_MATCH(DMI_PRODUCT_NAME, "PCG-FRV35"),
  244. },
  245. },
  246. /*
  247. * Toshiba models with Transflective display, these need to use
  248. * the toshiba_acpi vendor driver for proper Transflective handling.
  249. */
  250. {
  251. .callback = video_detect_force_vendor,
  252. .matches = {
  253. DMI_MATCH(DMI_SYS_VENDOR, "TOSHIBA"),
  254. DMI_MATCH(DMI_PRODUCT_NAME, "PORTEGE R500"),
  255. },
  256. },
  257. {
  258. .callback = video_detect_force_vendor,
  259. .matches = {
  260. DMI_MATCH(DMI_SYS_VENDOR, "TOSHIBA"),
  261. DMI_MATCH(DMI_PRODUCT_NAME, "PORTEGE R600"),
  262. },
  263. },
  264. /*
  265. * Toshiba Portégé R100 has working both acpi_video and toshiba_acpi
  266. * vendor driver. But none of them gets activated as it has a VGA with
  267. * no kernel driver (Trident CyberBlade XP4m32).
  268. * The DMI strings are generic so check for the VGA chip in callback.
  269. */
  270. {
  271. .callback = video_detect_portege_r100,
  272. .matches = {
  273. DMI_MATCH(DMI_SYS_VENDOR, "TOSHIBA"),
  274. DMI_MATCH(DMI_PRODUCT_NAME, "Portable PC"),
  275. DMI_MATCH(DMI_PRODUCT_VERSION, "Version 1.0"),
  276. DMI_MATCH(DMI_BOARD_NAME, "Portable PC")
  277. },
  278. },
  279. /*
  280. * Models which need acpi_video backlight control where the GPU drivers
  281. * do not call acpi_video_register_backlight() because no internal panel
  282. * is detected. Typically these are all-in-ones (monitors with builtin
  283. * PC) where the panel connection shows up as regular DP instead of eDP.
  284. */
  285. {
  286. .callback = video_detect_force_video,
  287. /* Apple iMac14,1 */
  288. .matches = {
  289. DMI_MATCH(DMI_SYS_VENDOR, "Apple Inc."),
  290. DMI_MATCH(DMI_PRODUCT_NAME, "iMac14,1"),
  291. },
  292. },
  293. {
  294. .callback = video_detect_force_video,
  295. /* Apple iMac14,2 */
  296. .matches = {
  297. DMI_MATCH(DMI_SYS_VENDOR, "Apple Inc."),
  298. DMI_MATCH(DMI_PRODUCT_NAME, "iMac14,2"),
  299. },
  300. },
  301. /*
  302. * These models have a working acpi_video backlight control, and using
  303. * native backlight causes a regression where backlight does not work
  304. * when userspace is not handling brightness key events. Disable
  305. * native_backlight on these to fix this:
  306. * https://bugzilla.kernel.org/show_bug.cgi?id=81691
  307. */
  308. {
  309. .callback = video_detect_force_video,
  310. /* ThinkPad T420 */
  311. .matches = {
  312. DMI_MATCH(DMI_SYS_VENDOR, "LENOVO"),
  313. DMI_MATCH(DMI_PRODUCT_VERSION, "ThinkPad T420"),
  314. },
  315. },
  316. {
  317. .callback = video_detect_force_video,
  318. /* ThinkPad T520 */
  319. .matches = {
  320. DMI_MATCH(DMI_SYS_VENDOR, "LENOVO"),
  321. DMI_MATCH(DMI_PRODUCT_VERSION, "ThinkPad T520"),
  322. },
  323. },
  324. {
  325. .callback = video_detect_force_video,
  326. /* ThinkPad X201s */
  327. .matches = {
  328. DMI_MATCH(DMI_SYS_VENDOR, "LENOVO"),
  329. DMI_MATCH(DMI_PRODUCT_VERSION, "ThinkPad X201s"),
  330. },
  331. },
  332. {
  333. .callback = video_detect_force_video,
  334. /* ThinkPad X201T */
  335. .matches = {
  336. DMI_MATCH(DMI_SYS_VENDOR, "LENOVO"),
  337. DMI_MATCH(DMI_PRODUCT_VERSION, "ThinkPad X201T"),
  338. },
  339. },
  340. /* The native backlight controls do not work on some older machines */
  341. {
  342. /* https://bugs.freedesktop.org/show_bug.cgi?id=81515 */
  343. .callback = video_detect_force_video,
  344. /* HP ENVY 15 Notebook */
  345. .matches = {
  346. DMI_MATCH(DMI_SYS_VENDOR, "Hewlett-Packard"),
  347. DMI_MATCH(DMI_PRODUCT_NAME, "HP ENVY 15 Notebook PC"),
  348. },
  349. },
  350. {
  351. .callback = video_detect_force_video,
  352. /* SAMSUNG 870Z5E/880Z5E/680Z5E */
  353. .matches = {
  354. DMI_MATCH(DMI_SYS_VENDOR, "SAMSUNG ELECTRONICS CO., LTD."),
  355. DMI_MATCH(DMI_PRODUCT_NAME, "870Z5E/880Z5E/680Z5E"),
  356. },
  357. },
  358. {
  359. .callback = video_detect_force_video,
  360. /* SAMSUNG 370R4E/370R4V/370R5E/3570RE/370R5V */
  361. .matches = {
  362. DMI_MATCH(DMI_SYS_VENDOR, "SAMSUNG ELECTRONICS CO., LTD."),
  363. DMI_MATCH(DMI_PRODUCT_NAME,
  364. "370R4E/370R4V/370R5E/3570RE/370R5V"),
  365. },
  366. },
  367. {
  368. /* https://bugzilla.redhat.com/show_bug.cgi?id=1186097 */
  369. .callback = video_detect_force_video,
  370. /* SAMSUNG 3570R/370R/470R/450R/510R/4450RV */
  371. .matches = {
  372. DMI_MATCH(DMI_SYS_VENDOR, "SAMSUNG ELECTRONICS CO., LTD."),
  373. DMI_MATCH(DMI_PRODUCT_NAME,
  374. "3570R/370R/470R/450R/510R/4450RV"),
  375. },
  376. },
  377. {
  378. /* https://bugzilla.redhat.com/show_bug.cgi?id=1557060 */
  379. .callback = video_detect_force_video,
  380. /* SAMSUNG 670Z5E */
  381. .matches = {
  382. DMI_MATCH(DMI_SYS_VENDOR, "SAMSUNG ELECTRONICS CO., LTD."),
  383. DMI_MATCH(DMI_PRODUCT_NAME, "670Z5E"),
  384. },
  385. },
  386. {
  387. /* https://bugzilla.redhat.com/show_bug.cgi?id=1094948 */
  388. .callback = video_detect_force_video,
  389. /* SAMSUNG 730U3E/740U3E */
  390. .matches = {
  391. DMI_MATCH(DMI_SYS_VENDOR, "SAMSUNG ELECTRONICS CO., LTD."),
  392. DMI_MATCH(DMI_PRODUCT_NAME, "730U3E/740U3E"),
  393. },
  394. },
  395. {
  396. /* https://bugs.freedesktop.org/show_bug.cgi?id=87286 */
  397. .callback = video_detect_force_video,
  398. /* SAMSUNG 900X3C/900X3D/900X3E/900X4C/900X4D */
  399. .matches = {
  400. DMI_MATCH(DMI_SYS_VENDOR, "SAMSUNG ELECTRONICS CO., LTD."),
  401. DMI_MATCH(DMI_PRODUCT_NAME,
  402. "900X3C/900X3D/900X3E/900X4C/900X4D"),
  403. },
  404. },
  405. {
  406. /* https://bugzilla.redhat.com/show_bug.cgi?id=1272633 */
  407. .callback = video_detect_force_video,
  408. /* Dell XPS14 L421X */
  409. .matches = {
  410. DMI_MATCH(DMI_SYS_VENDOR, "Dell Inc."),
  411. DMI_MATCH(DMI_PRODUCT_NAME, "XPS L421X"),
  412. },
  413. },
  414. {
  415. /* https://bugzilla.redhat.com/show_bug.cgi?id=1163574 */
  416. .callback = video_detect_force_video,
  417. /* Dell XPS15 L521X */
  418. .matches = {
  419. DMI_MATCH(DMI_SYS_VENDOR, "Dell Inc."),
  420. DMI_MATCH(DMI_PRODUCT_NAME, "XPS L521X"),
  421. },
  422. },
  423. {
  424. /* https://bugzilla.kernel.org/show_bug.cgi?id=108971 */
  425. .callback = video_detect_force_video,
  426. /* SAMSUNG 530U4E/540U4E */
  427. .matches = {
  428. DMI_MATCH(DMI_SYS_VENDOR, "SAMSUNG ELECTRONICS CO., LTD."),
  429. DMI_MATCH(DMI_PRODUCT_NAME, "530U4E/540U4E"),
  430. },
  431. },
  432. /* https://bugs.launchpad.net/bugs/1894667 */
  433. {
  434. .callback = video_detect_force_video,
  435. /* HP 635 Notebook */
  436. .matches = {
  437. DMI_MATCH(DMI_SYS_VENDOR, "Hewlett-Packard"),
  438. DMI_MATCH(DMI_PRODUCT_NAME, "HP 635 Notebook PC"),
  439. },
  440. },
  441. /* Non win8 machines which need native backlight nevertheless */
  442. {
  443. /* https://bugzilla.redhat.com/show_bug.cgi?id=1201530 */
  444. .callback = video_detect_force_native,
  445. /* Lenovo Ideapad S405 */
  446. .matches = {
  447. DMI_MATCH(DMI_SYS_VENDOR, "LENOVO"),
  448. DMI_MATCH(DMI_BOARD_NAME, "Lenovo IdeaPad S405"),
  449. },
  450. },
  451. {
  452. /* https://bugzilla.suse.com/show_bug.cgi?id=1208724 */
  453. .callback = video_detect_force_native,
  454. /* Lenovo Ideapad Z470 */
  455. .matches = {
  456. DMI_MATCH(DMI_SYS_VENDOR, "LENOVO"),
  457. DMI_MATCH(DMI_PRODUCT_VERSION, "IdeaPad Z470"),
  458. },
  459. },
  460. {
  461. /* https://bugzilla.redhat.com/show_bug.cgi?id=1187004 */
  462. .callback = video_detect_force_native,
  463. /* Lenovo Ideapad Z570 */
  464. .matches = {
  465. DMI_MATCH(DMI_SYS_VENDOR, "LENOVO"),
  466. DMI_MATCH(DMI_PRODUCT_VERSION, "Ideapad Z570"),
  467. },
  468. },
  469. {
  470. .callback = video_detect_force_native,
  471. /* Lenovo E41-25 */
  472. .matches = {
  473. DMI_MATCH(DMI_SYS_VENDOR, "LENOVO"),
  474. DMI_MATCH(DMI_PRODUCT_NAME, "81FS"),
  475. },
  476. },
  477. {
  478. .callback = video_detect_force_native,
  479. /* Lenovo E41-45 */
  480. .matches = {
  481. DMI_MATCH(DMI_SYS_VENDOR, "LENOVO"),
  482. DMI_MATCH(DMI_PRODUCT_NAME, "82BK"),
  483. },
  484. },
  485. {
  486. /* https://bugzilla.redhat.com/show_bug.cgi?id=1217249 */
  487. .callback = video_detect_force_native,
  488. /* Apple MacBook Pro 12,1 */
  489. .matches = {
  490. DMI_MATCH(DMI_SYS_VENDOR, "Apple Inc."),
  491. DMI_MATCH(DMI_PRODUCT_NAME, "MacBookPro12,1"),
  492. },
  493. },
  494. {
  495. .callback = video_detect_force_native,
  496. /* Dell Inspiron N4010 */
  497. .matches = {
  498. DMI_MATCH(DMI_SYS_VENDOR, "Dell Inc."),
  499. DMI_MATCH(DMI_PRODUCT_NAME, "Inspiron N4010"),
  500. },
  501. },
  502. {
  503. .callback = video_detect_force_native,
  504. /* Dell Vostro V131 */
  505. .matches = {
  506. DMI_MATCH(DMI_SYS_VENDOR, "Dell Inc."),
  507. DMI_MATCH(DMI_PRODUCT_NAME, "Vostro V131"),
  508. },
  509. },
  510. {
  511. /* https://bugzilla.redhat.com/show_bug.cgi?id=1123661 */
  512. .callback = video_detect_force_native,
  513. /* Dell XPS 17 L702X */
  514. .matches = {
  515. DMI_MATCH(DMI_SYS_VENDOR, "Dell Inc."),
  516. DMI_MATCH(DMI_PRODUCT_NAME, "Dell System XPS L702X"),
  517. },
  518. },
  519. {
  520. .callback = video_detect_force_native,
  521. /* Dell Precision 7510 */
  522. .matches = {
  523. DMI_MATCH(DMI_SYS_VENDOR, "Dell Inc."),
  524. DMI_MATCH(DMI_PRODUCT_NAME, "Precision 7510"),
  525. },
  526. },
  527. {
  528. .callback = video_detect_force_native,
  529. /* Dell Studio 1569 */
  530. .matches = {
  531. DMI_MATCH(DMI_SYS_VENDOR, "Dell Inc."),
  532. DMI_MATCH(DMI_PRODUCT_NAME, "Studio 1569"),
  533. },
  534. },
  535. {
  536. .callback = video_detect_force_native,
  537. /* Acer Aspire 3830TG */
  538. .matches = {
  539. DMI_MATCH(DMI_SYS_VENDOR, "Acer"),
  540. DMI_MATCH(DMI_PRODUCT_NAME, "Aspire 3830TG"),
  541. },
  542. },
  543. {
  544. .callback = video_detect_force_native,
  545. /* Acer Aspire 4810T */
  546. .matches = {
  547. DMI_MATCH(DMI_SYS_VENDOR, "Acer"),
  548. DMI_MATCH(DMI_PRODUCT_NAME, "Aspire 4810T"),
  549. },
  550. },
  551. {
  552. .callback = video_detect_force_native,
  553. /* Acer Aspire 5738z */
  554. .matches = {
  555. DMI_MATCH(DMI_SYS_VENDOR, "Acer"),
  556. DMI_MATCH(DMI_PRODUCT_NAME, "Aspire 5738"),
  557. DMI_MATCH(DMI_BOARD_NAME, "JV50"),
  558. },
  559. },
  560. {
  561. /* https://bugzilla.redhat.com/show_bug.cgi?id=1012674 */
  562. .callback = video_detect_force_native,
  563. /* Acer Aspire 5741 */
  564. .matches = {
  565. DMI_MATCH(DMI_BOARD_VENDOR, "Acer"),
  566. DMI_MATCH(DMI_PRODUCT_NAME, "Aspire 5741"),
  567. },
  568. },
  569. {
  570. /* https://bugzilla.kernel.org/show_bug.cgi?id=42993 */
  571. .callback = video_detect_force_native,
  572. /* Acer Aspire 5750 */
  573. .matches = {
  574. DMI_MATCH(DMI_BOARD_VENDOR, "Acer"),
  575. DMI_MATCH(DMI_PRODUCT_NAME, "Aspire 5750"),
  576. },
  577. },
  578. {
  579. /* https://bugzilla.kernel.org/show_bug.cgi?id=42833 */
  580. .callback = video_detect_force_native,
  581. /* Acer Extensa 5235 */
  582. .matches = {
  583. DMI_MATCH(DMI_BOARD_VENDOR, "Acer"),
  584. DMI_MATCH(DMI_PRODUCT_NAME, "Extensa 5235"),
  585. },
  586. },
  587. {
  588. .callback = video_detect_force_native,
  589. /* Acer TravelMate 4750 */
  590. .matches = {
  591. DMI_MATCH(DMI_BOARD_VENDOR, "Acer"),
  592. DMI_MATCH(DMI_PRODUCT_NAME, "TravelMate 4750"),
  593. },
  594. },
  595. {
  596. /* https://bugzilla.kernel.org/show_bug.cgi?id=207835 */
  597. .callback = video_detect_force_native,
  598. /* Acer TravelMate 5735Z */
  599. .matches = {
  600. DMI_MATCH(DMI_SYS_VENDOR, "Acer"),
  601. DMI_MATCH(DMI_PRODUCT_NAME, "TravelMate 5735Z"),
  602. DMI_MATCH(DMI_BOARD_NAME, "BA51_MV"),
  603. },
  604. },
  605. {
  606. /* https://bugzilla.kernel.org/show_bug.cgi?id=36322 */
  607. .callback = video_detect_force_native,
  608. /* Acer TravelMate 5760 */
  609. .matches = {
  610. DMI_MATCH(DMI_BOARD_VENDOR, "Acer"),
  611. DMI_MATCH(DMI_PRODUCT_NAME, "TravelMate 5760"),
  612. },
  613. },
  614. {
  615. .callback = video_detect_force_native,
  616. /* ASUSTeK COMPUTER INC. GA401 */
  617. .matches = {
  618. DMI_MATCH(DMI_SYS_VENDOR, "ASUSTeK COMPUTER INC."),
  619. DMI_MATCH(DMI_PRODUCT_NAME, "GA401"),
  620. },
  621. },
  622. {
  623. .callback = video_detect_force_native,
  624. /* ASUSTeK COMPUTER INC. GA502 */
  625. .matches = {
  626. DMI_MATCH(DMI_SYS_VENDOR, "ASUSTeK COMPUTER INC."),
  627. DMI_MATCH(DMI_PRODUCT_NAME, "GA502"),
  628. },
  629. },
  630. {
  631. .callback = video_detect_force_native,
  632. /* ASUSTeK COMPUTER INC. GA503 */
  633. .matches = {
  634. DMI_MATCH(DMI_SYS_VENDOR, "ASUSTeK COMPUTER INC."),
  635. DMI_MATCH(DMI_PRODUCT_NAME, "GA503"),
  636. },
  637. },
  638. {
  639. .callback = video_detect_force_native,
  640. /* Asus U46E */
  641. .matches = {
  642. DMI_MATCH(DMI_SYS_VENDOR, "ASUSTeK Computer Inc."),
  643. DMI_MATCH(DMI_PRODUCT_NAME, "U46E"),
  644. },
  645. },
  646. {
  647. .callback = video_detect_force_native,
  648. /* Asus UX303UB */
  649. .matches = {
  650. DMI_MATCH(DMI_SYS_VENDOR, "ASUSTeK COMPUTER INC."),
  651. DMI_MATCH(DMI_PRODUCT_NAME, "UX303UB"),
  652. },
  653. },
  654. {
  655. .callback = video_detect_force_native,
  656. /* HP EliteBook 8460p */
  657. .matches = {
  658. DMI_MATCH(DMI_SYS_VENDOR, "Hewlett-Packard"),
  659. DMI_MATCH(DMI_PRODUCT_NAME, "HP EliteBook 8460p"),
  660. },
  661. },
  662. {
  663. .callback = video_detect_force_native,
  664. /* HP Pavilion g6-1d80nr / B4U19UA */
  665. .matches = {
  666. DMI_MATCH(DMI_SYS_VENDOR, "Hewlett-Packard"),
  667. DMI_MATCH(DMI_PRODUCT_NAME, "HP Pavilion g6 Notebook PC"),
  668. DMI_MATCH(DMI_PRODUCT_SKU, "B4U19UA"),
  669. },
  670. },
  671. {
  672. .callback = video_detect_force_native,
  673. /* Samsung N150P */
  674. .matches = {
  675. DMI_MATCH(DMI_SYS_VENDOR, "SAMSUNG ELECTRONICS CO., LTD."),
  676. DMI_MATCH(DMI_PRODUCT_NAME, "N150P"),
  677. DMI_MATCH(DMI_BOARD_NAME, "N150P"),
  678. },
  679. },
  680. {
  681. .callback = video_detect_force_native,
  682. /* Samsung N145P/N250P/N260P */
  683. .matches = {
  684. DMI_MATCH(DMI_SYS_VENDOR, "SAMSUNG ELECTRONICS CO., LTD."),
  685. DMI_MATCH(DMI_PRODUCT_NAME, "N145P/N250P/N260P"),
  686. DMI_MATCH(DMI_BOARD_NAME, "N145P/N250P/N260P"),
  687. },
  688. },
  689. {
  690. .callback = video_detect_force_native,
  691. /* Samsung N250P */
  692. .matches = {
  693. DMI_MATCH(DMI_SYS_VENDOR, "SAMSUNG ELECTRONICS CO., LTD."),
  694. DMI_MATCH(DMI_PRODUCT_NAME, "N250P"),
  695. DMI_MATCH(DMI_BOARD_NAME, "N250P"),
  696. },
  697. },
  698. {
  699. /* https://bugzilla.kernel.org/show_bug.cgi?id=202401 */
  700. .callback = video_detect_force_native,
  701. /* Sony Vaio VPCEH3U1E */
  702. .matches = {
  703. DMI_MATCH(DMI_SYS_VENDOR, "Sony Corporation"),
  704. DMI_MATCH(DMI_PRODUCT_NAME, "VPCEH3U1E"),
  705. },
  706. },
  707. {
  708. .callback = video_detect_force_native,
  709. /* Sony Vaio VPCY11S1E */
  710. .matches = {
  711. DMI_MATCH(DMI_SYS_VENDOR, "Sony Corporation"),
  712. DMI_MATCH(DMI_PRODUCT_NAME, "VPCY11S1E"),
  713. },
  714. },
  715. /*
  716. * These Toshibas have a broken acpi-video interface for brightness
  717. * control. They also have an issue where the panel is off after
  718. * suspend until a special firmware call is made to turn it back
  719. * on. This is handled by the toshiba_acpi kernel module, so that
  720. * module must be enabled for these models to work correctly.
  721. */
  722. {
  723. /* https://bugzilla.kernel.org/show_bug.cgi?id=21012 */
  724. .callback = video_detect_force_native,
  725. /* Toshiba Portégé R700 */
  726. .matches = {
  727. DMI_MATCH(DMI_SYS_VENDOR, "TOSHIBA"),
  728. DMI_MATCH(DMI_PRODUCT_NAME, "PORTEGE R700"),
  729. },
  730. },
  731. {
  732. /* Portégé: https://bugs.freedesktop.org/show_bug.cgi?id=82634 */
  733. /* Satellite: https://bugzilla.kernel.org/show_bug.cgi?id=21012 */
  734. .callback = video_detect_force_native,
  735. /* Toshiba Satellite/Portégé R830 */
  736. .matches = {
  737. DMI_MATCH(DMI_SYS_VENDOR, "TOSHIBA"),
  738. DMI_MATCH(DMI_PRODUCT_NAME, "R830"),
  739. },
  740. },
  741. {
  742. .callback = video_detect_force_native,
  743. /* Toshiba Satellite/Portégé Z830 */
  744. .matches = {
  745. DMI_MATCH(DMI_SYS_VENDOR, "TOSHIBA"),
  746. DMI_MATCH(DMI_PRODUCT_NAME, "Z830"),
  747. },
  748. },
  749. /*
  750. * Models which have nvidia-ec-wmi support, but should not use it.
  751. * Note this indicates a likely firmware bug on these models and should
  752. * be revisited if/when Linux gets support for dynamic mux mode.
  753. */
  754. {
  755. .callback = video_detect_force_native,
  756. /* Dell G15 5515 */
  757. .matches = {
  758. DMI_MATCH(DMI_SYS_VENDOR, "Dell Inc."),
  759. DMI_MATCH(DMI_PRODUCT_NAME, "Dell G15 5515"),
  760. },
  761. },
  762. {
  763. .callback = video_detect_force_native,
  764. .matches = {
  765. DMI_MATCH(DMI_SYS_VENDOR, "Dell Inc."),
  766. DMI_MATCH(DMI_PRODUCT_NAME, "Vostro 15 3535"),
  767. },
  768. },
  769. { },
  770. };
  771. static bool google_cros_ec_present(void)
  772. {
  773. return acpi_dev_found("GOOG0004") || acpi_dev_found("GOOG000C");
  774. }
  775. /*
  776. * Windows 8 and newer no longer use the ACPI video interface, so it often
  777. * does not work. So on win8+ systems prefer native brightness control.
  778. * Chromebooks should always prefer native backlight control.
  779. */
  780. static bool prefer_native_over_acpi_video(void)
  781. {
  782. return acpi_osi_is_win8() || google_cros_ec_present();
  783. }
  784. /*
  785. * Determine which type of backlight interface to use on this system,
  786. * First check cmdline, then dmi quirks, then do autodetect.
  787. */
  788. enum acpi_backlight_type __acpi_video_get_backlight_type(bool native, bool *auto_detect)
  789. {
  790. static DEFINE_MUTEX(init_mutex);
  791. static bool nvidia_wmi_ec_present;
  792. static bool apple_gmux_present;
  793. static bool native_available;
  794. static bool init_done;
  795. static long video_caps;
  796. /* Parse cmdline, dmi and acpi only once */
  797. mutex_lock(&init_mutex);
  798. if (!init_done) {
  799. acpi_video_parse_cmdline();
  800. dmi_check_system(video_detect_dmi_table);
  801. acpi_walk_namespace(ACPI_TYPE_DEVICE, ACPI_ROOT_OBJECT,
  802. ACPI_UINT32_MAX, find_video, NULL,
  803. &video_caps, NULL);
  804. nvidia_wmi_ec_present = nvidia_wmi_ec_supported();
  805. apple_gmux_present = apple_gmux_detect(NULL, NULL);
  806. init_done = true;
  807. }
  808. if (native)
  809. native_available = true;
  810. mutex_unlock(&init_mutex);
  811. if (auto_detect)
  812. *auto_detect = false;
  813. /*
  814. * The below heuristics / detection steps are in order of descending
  815. * presedence. The commandline takes presedence over anything else.
  816. */
  817. if (acpi_backlight_cmdline != acpi_backlight_undef)
  818. return acpi_backlight_cmdline;
  819. /* DMI quirks override any autodetection. */
  820. if (acpi_backlight_dmi != acpi_backlight_undef)
  821. return acpi_backlight_dmi;
  822. if (auto_detect)
  823. *auto_detect = true;
  824. /* Special cases such as nvidia_wmi_ec and apple gmux. */
  825. if (nvidia_wmi_ec_present)
  826. return acpi_backlight_nvidia_wmi_ec;
  827. if (apple_gmux_present)
  828. return acpi_backlight_apple_gmux;
  829. /* Use ACPI video if available, except when native should be preferred. */
  830. if ((video_caps & ACPI_VIDEO_BACKLIGHT) &&
  831. !(native_available && prefer_native_over_acpi_video()))
  832. return acpi_backlight_video;
  833. /* Use native if available */
  834. if (native_available)
  835. return acpi_backlight_native;
  836. /* No ACPI video/native (old hw), use vendor specific fw methods. */
  837. return acpi_backlight_vendor;
  838. }
  839. EXPORT_SYMBOL(__acpi_video_get_backlight_type);