ACPI: video: Add force_native quirk for Sony Vaio VPCY11S1E
[platform/kernel/linux-starfive.git] / drivers / acpi / video_detect.c
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          .callback = video_detect_force_vendor,
174          /* Asus X101CH */
175          .matches = {
176                 DMI_MATCH(DMI_SYS_VENDOR, "ASUSTeK COMPUTER INC."),
177                 DMI_MATCH(DMI_PRODUCT_NAME, "X101CH"),
178                 },
179         },
180         {
181          .callback = video_detect_force_vendor,
182          /* Asus X401U */
183          .matches = {
184                 DMI_MATCH(DMI_SYS_VENDOR, "ASUSTeK COMPUTER INC."),
185                 DMI_MATCH(DMI_PRODUCT_NAME, "X401U"),
186                 },
187         },
188         {
189          .callback = video_detect_force_vendor,
190          /* Asus X501U */
191          .matches = {
192                 DMI_MATCH(DMI_SYS_VENDOR, "ASUSTeK COMPUTER INC."),
193                 DMI_MATCH(DMI_PRODUCT_NAME, "X501U"),
194                 },
195         },
196         {
197          .callback = video_detect_force_vendor,
198          /* Asus 1015CX */
199          .matches = {
200                 DMI_MATCH(DMI_SYS_VENDOR, "ASUSTeK COMPUTER INC."),
201                 DMI_MATCH(DMI_PRODUCT_NAME, "1015CX"),
202                 },
203         },
204         {
205          .callback = video_detect_force_vendor,
206          /* Samsung N150/N210/N220 */
207          .matches = {
208                 DMI_MATCH(DMI_SYS_VENDOR, "SAMSUNG ELECTRONICS CO., LTD."),
209                 DMI_MATCH(DMI_PRODUCT_NAME, "N150/N210/N220"),
210                 DMI_MATCH(DMI_BOARD_NAME, "N150/N210/N220"),
211                 },
212         },
213         {
214          .callback = video_detect_force_vendor,
215          /* Samsung NF110/NF210/NF310 */
216          .matches = {
217                 DMI_MATCH(DMI_SYS_VENDOR, "SAMSUNG ELECTRONICS CO., LTD."),
218                 DMI_MATCH(DMI_PRODUCT_NAME, "NF110/NF210/NF310"),
219                 DMI_MATCH(DMI_BOARD_NAME, "NF110/NF210/NF310"),
220                 },
221         },
222         {
223          .callback = video_detect_force_vendor,
224          /* Samsung NC210 */
225          .matches = {
226                 DMI_MATCH(DMI_SYS_VENDOR, "SAMSUNG ELECTRONICS CO., LTD."),
227                 DMI_MATCH(DMI_PRODUCT_NAME, "NC210/NC110"),
228                 DMI_MATCH(DMI_BOARD_NAME, "NC210/NC110"),
229                 },
230         },
231         {
232          .callback = video_detect_force_vendor,
233          /* Xiaomi Mi Pad 2 */
234          .matches = {
235                         DMI_MATCH(DMI_SYS_VENDOR, "Xiaomi Inc"),
236                         DMI_MATCH(DMI_PRODUCT_NAME, "Mipad2"),
237                 },
238         },
239
240         /*
241          * Models which should use the vendor backlight interface,
242          * because of broken native backlight control.
243          */
244         {
245          .callback = video_detect_force_vendor,
246          /* Sony Vaio PCG-FRV35 */
247          .matches = {
248                 DMI_MATCH(DMI_SYS_VENDOR, "Sony Corporation"),
249                 DMI_MATCH(DMI_PRODUCT_NAME, "PCG-FRV35"),
250                 },
251         },
252
253         /*
254          * Toshiba models with Transflective display, these need to use
255          * the toshiba_acpi vendor driver for proper Transflective handling.
256          */
257         {
258          .callback = video_detect_force_vendor,
259          .matches = {
260                 DMI_MATCH(DMI_SYS_VENDOR, "TOSHIBA"),
261                 DMI_MATCH(DMI_PRODUCT_NAME, "PORTEGE R500"),
262                 },
263         },
264         {
265          .callback = video_detect_force_vendor,
266          .matches = {
267                 DMI_MATCH(DMI_SYS_VENDOR, "TOSHIBA"),
268                 DMI_MATCH(DMI_PRODUCT_NAME, "PORTEGE R600"),
269                 },
270         },
271
272         /*
273          * These models have a working acpi_video backlight control, and using
274          * native backlight causes a regression where backlight does not work
275          * when userspace is not handling brightness key events. Disable
276          * native_backlight on these to fix this:
277          * https://bugzilla.kernel.org/show_bug.cgi?id=81691
278          */
279         {
280          .callback = video_detect_force_video,
281          /* ThinkPad T420 */
282          .matches = {
283                 DMI_MATCH(DMI_SYS_VENDOR, "LENOVO"),
284                 DMI_MATCH(DMI_PRODUCT_VERSION, "ThinkPad T420"),
285                 },
286         },
287         {
288          .callback = video_detect_force_video,
289          /* ThinkPad T520 */
290          .matches = {
291                 DMI_MATCH(DMI_SYS_VENDOR, "LENOVO"),
292                 DMI_MATCH(DMI_PRODUCT_VERSION, "ThinkPad T520"),
293                 },
294         },
295         {
296          .callback = video_detect_force_video,
297          /* ThinkPad X201s */
298          .matches = {
299                 DMI_MATCH(DMI_SYS_VENDOR, "LENOVO"),
300                 DMI_MATCH(DMI_PRODUCT_VERSION, "ThinkPad X201s"),
301                 },
302         },
303         {
304          .callback = video_detect_force_video,
305          /* ThinkPad X201T */
306          .matches = {
307                 DMI_MATCH(DMI_SYS_VENDOR, "LENOVO"),
308                 DMI_MATCH(DMI_PRODUCT_VERSION, "ThinkPad X201T"),
309                 },
310         },
311
312         /* The native backlight controls do not work on some older machines */
313         {
314          /* https://bugs.freedesktop.org/show_bug.cgi?id=81515 */
315          .callback = video_detect_force_video,
316          /* HP ENVY 15 Notebook */
317          .matches = {
318                 DMI_MATCH(DMI_SYS_VENDOR, "Hewlett-Packard"),
319                 DMI_MATCH(DMI_PRODUCT_NAME, "HP ENVY 15 Notebook PC"),
320                 },
321         },
322         {
323          .callback = video_detect_force_video,
324          /* SAMSUNG 870Z5E/880Z5E/680Z5E */
325          .matches = {
326                 DMI_MATCH(DMI_SYS_VENDOR, "SAMSUNG ELECTRONICS CO., LTD."),
327                 DMI_MATCH(DMI_PRODUCT_NAME, "870Z5E/880Z5E/680Z5E"),
328                 },
329         },
330         {
331          .callback = video_detect_force_video,
332          /* SAMSUNG 370R4E/370R4V/370R5E/3570RE/370R5V */
333          .matches = {
334                 DMI_MATCH(DMI_SYS_VENDOR, "SAMSUNG ELECTRONICS CO., LTD."),
335                 DMI_MATCH(DMI_PRODUCT_NAME,
336                           "370R4E/370R4V/370R5E/3570RE/370R5V"),
337                 },
338         },
339         {
340          /* https://bugzilla.redhat.com/show_bug.cgi?id=1186097 */
341          .callback = video_detect_force_video,
342          /* SAMSUNG 3570R/370R/470R/450R/510R/4450RV */
343          .matches = {
344                 DMI_MATCH(DMI_SYS_VENDOR, "SAMSUNG ELECTRONICS CO., LTD."),
345                 DMI_MATCH(DMI_PRODUCT_NAME,
346                           "3570R/370R/470R/450R/510R/4450RV"),
347                 },
348         },
349         {
350          /* https://bugzilla.redhat.com/show_bug.cgi?id=1557060 */
351          .callback = video_detect_force_video,
352          /* SAMSUNG 670Z5E */
353          .matches = {
354                 DMI_MATCH(DMI_SYS_VENDOR, "SAMSUNG ELECTRONICS CO., LTD."),
355                 DMI_MATCH(DMI_PRODUCT_NAME, "670Z5E"),
356                 },
357         },
358         {
359          /* https://bugzilla.redhat.com/show_bug.cgi?id=1094948 */
360          .callback = video_detect_force_video,
361          /* SAMSUNG 730U3E/740U3E */
362          .matches = {
363                 DMI_MATCH(DMI_SYS_VENDOR, "SAMSUNG ELECTRONICS CO., LTD."),
364                 DMI_MATCH(DMI_PRODUCT_NAME, "730U3E/740U3E"),
365                 },
366         },
367         {
368          /* https://bugs.freedesktop.org/show_bug.cgi?id=87286 */
369          .callback = video_detect_force_video,
370          /* SAMSUNG 900X3C/900X3D/900X3E/900X4C/900X4D */
371          .matches = {
372                 DMI_MATCH(DMI_SYS_VENDOR, "SAMSUNG ELECTRONICS CO., LTD."),
373                 DMI_MATCH(DMI_PRODUCT_NAME,
374                           "900X3C/900X3D/900X3E/900X4C/900X4D"),
375                 },
376         },
377         {
378          /* https://bugzilla.redhat.com/show_bug.cgi?id=1272633 */
379          .callback = video_detect_force_video,
380          /* Dell XPS14 L421X */
381          .matches = {
382                 DMI_MATCH(DMI_SYS_VENDOR, "Dell Inc."),
383                 DMI_MATCH(DMI_PRODUCT_NAME, "XPS L421X"),
384                 },
385         },
386         {
387          /* https://bugzilla.redhat.com/show_bug.cgi?id=1163574 */
388          .callback = video_detect_force_video,
389          /* Dell XPS15 L521X */
390          .matches = {
391                 DMI_MATCH(DMI_SYS_VENDOR, "Dell Inc."),
392                 DMI_MATCH(DMI_PRODUCT_NAME, "XPS L521X"),
393                 },
394         },
395         {
396          /* https://bugzilla.kernel.org/show_bug.cgi?id=108971 */
397          .callback = video_detect_force_video,
398          /* SAMSUNG 530U4E/540U4E */
399          .matches = {
400                 DMI_MATCH(DMI_SYS_VENDOR, "SAMSUNG ELECTRONICS CO., LTD."),
401                 DMI_MATCH(DMI_PRODUCT_NAME, "530U4E/540U4E"),
402                 },
403         },
404         /* https://bugs.launchpad.net/bugs/1894667 */
405         {
406          .callback = video_detect_force_video,
407          /* HP 635 Notebook */
408          .matches = {
409                 DMI_MATCH(DMI_SYS_VENDOR, "Hewlett-Packard"),
410                 DMI_MATCH(DMI_PRODUCT_NAME, "HP 635 Notebook PC"),
411                 },
412         },
413
414         /* Non win8 machines which need native backlight nevertheless */
415         {
416          /* https://bugzilla.redhat.com/show_bug.cgi?id=1201530 */
417          .callback = video_detect_force_native,
418          /* Lenovo Ideapad S405 */
419          .matches = {
420                 DMI_MATCH(DMI_SYS_VENDOR, "LENOVO"),
421                 DMI_MATCH(DMI_BOARD_NAME, "Lenovo IdeaPad S405"),
422                 },
423         },
424         {
425          /* https://bugzilla.redhat.com/show_bug.cgi?id=1187004 */
426          .callback = video_detect_force_native,
427          /* Lenovo Ideapad Z570 */
428          .matches = {
429                 DMI_MATCH(DMI_SYS_VENDOR, "LENOVO"),
430                 DMI_MATCH(DMI_PRODUCT_NAME, "102434U"),
431                 },
432         },
433         {
434          .callback = video_detect_force_native,
435          /* Lenovo E41-25 */
436          .matches = {
437                 DMI_MATCH(DMI_SYS_VENDOR, "LENOVO"),
438                 DMI_MATCH(DMI_PRODUCT_NAME, "81FS"),
439                 },
440         },
441         {
442          .callback = video_detect_force_native,
443          /* Lenovo E41-45 */
444          .matches = {
445                 DMI_MATCH(DMI_SYS_VENDOR, "LENOVO"),
446                 DMI_MATCH(DMI_PRODUCT_NAME, "82BK"),
447                 },
448         },
449         {
450          /* https://bugzilla.redhat.com/show_bug.cgi?id=1217249 */
451          .callback = video_detect_force_native,
452          /* Apple MacBook Pro 12,1 */
453          .matches = {
454                 DMI_MATCH(DMI_SYS_VENDOR, "Apple Inc."),
455                 DMI_MATCH(DMI_PRODUCT_NAME, "MacBookPro12,1"),
456                 },
457         },
458         {
459          .callback = video_detect_force_native,
460          /* Dell Inspiron N4010 */
461          .matches = {
462                 DMI_MATCH(DMI_SYS_VENDOR, "Dell Inc."),
463                 DMI_MATCH(DMI_PRODUCT_NAME, "Inspiron N4010"),
464                 },
465         },
466         {
467          .callback = video_detect_force_native,
468          /* Dell Vostro V131 */
469          .matches = {
470                 DMI_MATCH(DMI_SYS_VENDOR, "Dell Inc."),
471                 DMI_MATCH(DMI_PRODUCT_NAME, "Vostro V131"),
472                 },
473         },
474         {
475          /* https://bugzilla.redhat.com/show_bug.cgi?id=1123661 */
476          .callback = video_detect_force_native,
477          /* Dell XPS 17 L702X */
478          .matches = {
479                 DMI_MATCH(DMI_SYS_VENDOR, "Dell Inc."),
480                 DMI_MATCH(DMI_PRODUCT_NAME, "Dell System XPS L702X"),
481                 },
482         },
483         {
484          .callback = video_detect_force_native,
485          /* Dell Precision 7510 */
486          .matches = {
487                 DMI_MATCH(DMI_SYS_VENDOR, "Dell Inc."),
488                 DMI_MATCH(DMI_PRODUCT_NAME, "Precision 7510"),
489                 },
490         },
491         {
492          .callback = video_detect_force_native,
493          /* Acer Aspire 5738z */
494          .matches = {
495                 DMI_MATCH(DMI_SYS_VENDOR, "Acer"),
496                 DMI_MATCH(DMI_PRODUCT_NAME, "Aspire 5738"),
497                 DMI_MATCH(DMI_BOARD_NAME, "JV50"),
498                 },
499         },
500         {
501          /* https://bugzilla.redhat.com/show_bug.cgi?id=1012674 */
502          .callback = video_detect_force_native,
503          /* Acer Aspire 5741 */
504          .matches = {
505                 DMI_MATCH(DMI_BOARD_VENDOR, "Acer"),
506                 DMI_MATCH(DMI_PRODUCT_NAME, "Aspire 5741"),
507                 },
508         },
509         {
510          /* https://bugzilla.kernel.org/show_bug.cgi?id=42993 */
511          .callback = video_detect_force_native,
512          /* Acer Aspire 5750 */
513          .matches = {
514                 DMI_MATCH(DMI_BOARD_VENDOR, "Acer"),
515                 DMI_MATCH(DMI_PRODUCT_NAME, "Aspire 5750"),
516                 },
517         },
518         {
519          /* https://bugzilla.kernel.org/show_bug.cgi?id=42833 */
520          .callback = video_detect_force_native,
521          /* Acer Extensa 5235 */
522          .matches = {
523                 DMI_MATCH(DMI_BOARD_VENDOR, "Acer"),
524                 DMI_MATCH(DMI_PRODUCT_NAME, "Extensa 5235"),
525                 },
526         },
527         {
528          .callback = video_detect_force_native,
529          /* Acer TravelMate 4750 */
530          .matches = {
531                 DMI_MATCH(DMI_BOARD_VENDOR, "Acer"),
532                 DMI_MATCH(DMI_PRODUCT_NAME, "TravelMate 4750"),
533                 },
534         },
535         {
536          /* https://bugzilla.kernel.org/show_bug.cgi?id=207835 */
537          .callback = video_detect_force_native,
538          /* Acer TravelMate 5735Z */
539          .matches = {
540                 DMI_MATCH(DMI_SYS_VENDOR, "Acer"),
541                 DMI_MATCH(DMI_PRODUCT_NAME, "TravelMate 5735Z"),
542                 DMI_MATCH(DMI_BOARD_NAME, "BA51_MV"),
543                 },
544         },
545         {
546          /* https://bugzilla.kernel.org/show_bug.cgi?id=36322 */
547          .callback = video_detect_force_native,
548          /* Acer TravelMate 5760 */
549          .matches = {
550                 DMI_MATCH(DMI_BOARD_VENDOR, "Acer"),
551                 DMI_MATCH(DMI_PRODUCT_NAME, "TravelMate 5760"),
552                 },
553         },
554         {
555          .callback = video_detect_force_native,
556          /* ASUSTeK COMPUTER INC. GA401 */
557          .matches = {
558                 DMI_MATCH(DMI_SYS_VENDOR, "ASUSTeK COMPUTER INC."),
559                 DMI_MATCH(DMI_PRODUCT_NAME, "GA401"),
560                 },
561         },
562         {
563          .callback = video_detect_force_native,
564          /* ASUSTeK COMPUTER INC. GA502 */
565          .matches = {
566                 DMI_MATCH(DMI_SYS_VENDOR, "ASUSTeK COMPUTER INC."),
567                 DMI_MATCH(DMI_PRODUCT_NAME, "GA502"),
568                 },
569         },
570         {
571          .callback = video_detect_force_native,
572          /* ASUSTeK COMPUTER INC. GA503 */
573          .matches = {
574                 DMI_MATCH(DMI_SYS_VENDOR, "ASUSTeK COMPUTER INC."),
575                 DMI_MATCH(DMI_PRODUCT_NAME, "GA503"),
576                 },
577         },
578         {
579          .callback = video_detect_force_native,
580          /* Asus UX303UB */
581          .matches = {
582                 DMI_MATCH(DMI_SYS_VENDOR, "ASUSTeK COMPUTER INC."),
583                 DMI_MATCH(DMI_PRODUCT_NAME, "UX303UB"),
584                 },
585         },
586         {
587          .callback = video_detect_force_native,
588          /* Samsung N150P */
589          .matches = {
590                 DMI_MATCH(DMI_SYS_VENDOR, "SAMSUNG ELECTRONICS CO., LTD."),
591                 DMI_MATCH(DMI_PRODUCT_NAME, "N150P"),
592                 DMI_MATCH(DMI_BOARD_NAME, "N150P"),
593                 },
594         },
595         {
596          .callback = video_detect_force_native,
597          /* Samsung N145P/N250P/N260P */
598          .matches = {
599                 DMI_MATCH(DMI_SYS_VENDOR, "SAMSUNG ELECTRONICS CO., LTD."),
600                 DMI_MATCH(DMI_PRODUCT_NAME, "N145P/N250P/N260P"),
601                 DMI_MATCH(DMI_BOARD_NAME, "N145P/N250P/N260P"),
602                 },
603         },
604         {
605          .callback = video_detect_force_native,
606          /* Samsung N250P */
607          .matches = {
608                 DMI_MATCH(DMI_SYS_VENDOR, "SAMSUNG ELECTRONICS CO., LTD."),
609                 DMI_MATCH(DMI_PRODUCT_NAME, "N250P"),
610                 DMI_MATCH(DMI_BOARD_NAME, "N250P"),
611                 },
612         },
613         {
614          /* https://bugzilla.kernel.org/show_bug.cgi?id=202401 */
615          .callback = video_detect_force_native,
616          /* Sony Vaio VPCEH3U1E */
617          .matches = {
618                 DMI_MATCH(DMI_SYS_VENDOR, "Sony Corporation"),
619                 DMI_MATCH(DMI_PRODUCT_NAME, "VPCEH3U1E"),
620                 },
621         },
622         {
623          .callback = video_detect_force_native,
624          /* Sony Vaio VPCY11S1E */
625          .matches = {
626                 DMI_MATCH(DMI_SYS_VENDOR, "Sony Corporation"),
627                 DMI_MATCH(DMI_PRODUCT_NAME, "VPCY11S1E"),
628                 },
629         },
630
631         /*
632          * These Toshibas have a broken acpi-video interface for brightness
633          * control. They also have an issue where the panel is off after
634          * suspend until a special firmware call is made to turn it back
635          * on. This is handled by the toshiba_acpi kernel module, so that
636          * module must be enabled for these models to work correctly.
637          */
638         {
639          /* https://bugzilla.kernel.org/show_bug.cgi?id=21012 */
640          .callback = video_detect_force_native,
641          /* Toshiba Portégé R700 */
642          .matches = {
643                 DMI_MATCH(DMI_SYS_VENDOR, "TOSHIBA"),
644                 DMI_MATCH(DMI_PRODUCT_NAME, "PORTEGE R700"),
645                 },
646         },
647         {
648          /* Portégé: https://bugs.freedesktop.org/show_bug.cgi?id=82634 */
649          /* Satellite: https://bugzilla.kernel.org/show_bug.cgi?id=21012 */
650          .callback = video_detect_force_native,
651          /* Toshiba Satellite/Portégé R830 */
652          .matches = {
653                 DMI_MATCH(DMI_SYS_VENDOR, "TOSHIBA"),
654                 DMI_MATCH(DMI_PRODUCT_NAME, "R830"),
655                 },
656         },
657         {
658          .callback = video_detect_force_native,
659          /* Toshiba Satellite/Portégé Z830 */
660          .matches = {
661                 DMI_MATCH(DMI_SYS_VENDOR, "TOSHIBA"),
662                 DMI_MATCH(DMI_PRODUCT_NAME, "Z830"),
663                 },
664         },
665
666         /*
667          * Models which have nvidia-ec-wmi support, but should not use it.
668          * Note this indicates a likely firmware bug on these models and should
669          * be revisited if/when Linux gets support for dynamic mux mode.
670          */
671         {
672          .callback = video_detect_force_native,
673          /* Dell G15 5515 */
674          .matches = {
675                 DMI_MATCH(DMI_SYS_VENDOR, "Dell Inc."),
676                 DMI_MATCH(DMI_PRODUCT_NAME, "Dell G15 5515"),
677                 },
678         },
679
680         /*
681          * Desktops which falsely report a backlight and which our heuristics
682          * for this do not catch.
683          */
684         {
685          .callback = video_detect_force_none,
686          /* Dell OptiPlex 9020M */
687          .matches = {
688                 DMI_MATCH(DMI_SYS_VENDOR, "Dell Inc."),
689                 DMI_MATCH(DMI_PRODUCT_NAME, "OptiPlex 9020M"),
690                 },
691         },
692         {
693          .callback = video_detect_force_none,
694          /* GIGABYTE GB-BXBT-2807 */
695          .matches = {
696                 DMI_MATCH(DMI_SYS_VENDOR, "GIGABYTE"),
697                 DMI_MATCH(DMI_PRODUCT_NAME, "GB-BXBT-2807"),
698                 },
699         },
700         {
701          .callback = video_detect_force_none,
702          /* MSI MS-7721 */
703          .matches = {
704                 DMI_MATCH(DMI_SYS_VENDOR, "MSI"),
705                 DMI_MATCH(DMI_PRODUCT_NAME, "MS-7721"),
706                 },
707         },
708         { },
709 };
710
711 static bool google_cros_ec_present(void)
712 {
713         return acpi_dev_found("GOOG0004") || acpi_dev_found("GOOG000C");
714 }
715
716 /*
717  * Determine which type of backlight interface to use on this system,
718  * First check cmdline, then dmi quirks, then do autodetect.
719  */
720 static enum acpi_backlight_type __acpi_video_get_backlight_type(bool native)
721 {
722         static DEFINE_MUTEX(init_mutex);
723         static bool nvidia_wmi_ec_present;
724         static bool native_available;
725         static bool init_done;
726         static long video_caps;
727
728         /* Parse cmdline, dmi and acpi only once */
729         mutex_lock(&init_mutex);
730         if (!init_done) {
731                 acpi_video_parse_cmdline();
732                 dmi_check_system(video_detect_dmi_table);
733                 acpi_walk_namespace(ACPI_TYPE_DEVICE, ACPI_ROOT_OBJECT,
734                                     ACPI_UINT32_MAX, find_video, NULL,
735                                     &video_caps, NULL);
736                 nvidia_wmi_ec_present = nvidia_wmi_ec_supported();
737                 init_done = true;
738         }
739         if (native)
740                 native_available = true;
741         mutex_unlock(&init_mutex);
742
743         /*
744          * The below heuristics / detection steps are in order of descending
745          * presedence. The commandline takes presedence over anything else.
746          */
747         if (acpi_backlight_cmdline != acpi_backlight_undef)
748                 return acpi_backlight_cmdline;
749
750         /* DMI quirks override any autodetection. */
751         if (acpi_backlight_dmi != acpi_backlight_undef)
752                 return acpi_backlight_dmi;
753
754         /* Special cases such as nvidia_wmi_ec and apple gmux. */
755         if (nvidia_wmi_ec_present)
756                 return acpi_backlight_nvidia_wmi_ec;
757
758         if (apple_gmux_present())
759                 return acpi_backlight_apple_gmux;
760
761         /* Chromebooks should always prefer native backlight control. */
762         if (google_cros_ec_present() && native_available)
763                 return acpi_backlight_native;
764
765         /* On systems with ACPI video use either native or ACPI video. */
766         if (video_caps & ACPI_VIDEO_BACKLIGHT) {
767                 /*
768                  * Windows 8 and newer no longer use the ACPI video interface,
769                  * so it often does not work. If the ACPI tables are written
770                  * for win8 and native brightness ctl is available, use that.
771                  *
772                  * The native check deliberately is inside the if acpi-video
773                  * block on older devices without acpi-video support native
774                  * is usually not the best choice.
775                  */
776                 if (acpi_osi_is_win8() && native_available)
777                         return acpi_backlight_native;
778                 else
779                         return acpi_backlight_video;
780         }
781
782         /* No ACPI video (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         /*
795          * Call __acpi_video_get_backlight_type() to let it know that
796          * a native backlight is available.
797          */
798         __acpi_video_get_backlight_type(true);
799
800         /*
801          * For now just always return true. There is a whole bunch of laptop
802          * models where (video_caps & ACPI_VIDEO_BACKLIGHT) is false causing
803          * __acpi_video_get_backlight_type() to return vendor, while these
804          * models only have a native backlight control.
805          */
806         return true;
807 }
808 EXPORT_SYMBOL(acpi_video_backlight_use_native);