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