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