1 // SPDX-License-Identifier: MIT 2 /* 3 * Copyright © 2018 Intel Corporation 4 */ 5 6 #include <linux/dmi.h> 7 8 #include "i915_drv.h" 9 #include "intel_display_types.h" 10 #include "intel_quirks.h" 11 12 /* 13 * Some machines (Lenovo U160) do not work with SSC on LVDS for some reason 14 */ 15 static void quirk_ssc_force_disable(struct drm_i915_private *i915) 16 { 17 i915->quirks |= QUIRK_LVDS_SSC_DISABLE; 18 drm_info(&i915->drm, "applying lvds SSC disable quirk\n"); 19 } 20 21 /* 22 * A machine (e.g. Acer Aspire 5734Z) may need to invert the panel backlight 23 * brightness value 24 */ 25 static void quirk_invert_brightness(struct drm_i915_private *i915) 26 { 27 i915->quirks |= QUIRK_INVERT_BRIGHTNESS; 28 drm_info(&i915->drm, "applying inverted panel brightness quirk\n"); 29 } 30 31 /* Some VBT's incorrectly indicate no backlight is present */ 32 static void quirk_backlight_present(struct drm_i915_private *i915) 33 { 34 i915->quirks |= QUIRK_BACKLIGHT_PRESENT; 35 drm_info(&i915->drm, "applying backlight present quirk\n"); 36 } 37 38 /* Toshiba Satellite P50-C-18C requires T12 delay to be min 800ms 39 * which is 300 ms greater than eDP spec T12 min. 40 */ 41 static void quirk_increase_t12_delay(struct drm_i915_private *i915) 42 { 43 i915->quirks |= QUIRK_INCREASE_T12_DELAY; 44 drm_info(&i915->drm, "Applying T12 delay quirk\n"); 45 } 46 47 /* 48 * GeminiLake NUC HDMI outputs require additional off time 49 * this allows the onboard retimer to correctly sync to signal 50 */ 51 static void quirk_increase_ddi_disabled_time(struct drm_i915_private *i915) 52 { 53 i915->quirks |= QUIRK_INCREASE_DDI_DISABLED_TIME; 54 drm_info(&i915->drm, "Applying Increase DDI Disabled quirk\n"); 55 } 56 57 static void quirk_no_pps_backlight_power_hook(struct drm_i915_private *i915) 58 { 59 i915->quirks |= QUIRK_NO_PPS_BACKLIGHT_POWER_HOOK; 60 drm_info(&i915->drm, "Applying no pps backlight power quirk\n"); 61 } 62 63 struct intel_quirk { 64 int device; 65 int subsystem_vendor; 66 int subsystem_device; 67 void (*hook)(struct drm_i915_private *i915); 68 }; 69 70 /* For systems that don't have a meaningful PCI subdevice/subvendor ID */ 71 struct intel_dmi_quirk { 72 void (*hook)(struct drm_i915_private *i915); 73 const struct dmi_system_id (*dmi_id_list)[]; 74 }; 75 76 static int intel_dmi_reverse_brightness(const struct dmi_system_id *id) 77 { 78 DRM_INFO("Backlight polarity reversed on %s\n", id->ident); 79 return 1; 80 } 81 82 static int intel_dmi_no_pps_backlight(const struct dmi_system_id *id) 83 { 84 DRM_INFO("No pps backlight support on %s\n", id->ident); 85 return 1; 86 } 87 88 static const struct intel_dmi_quirk intel_dmi_quirks[] = { 89 { 90 .dmi_id_list = &(const struct dmi_system_id[]) { 91 { 92 .callback = intel_dmi_reverse_brightness, 93 .ident = "NCR Corporation", 94 .matches = {DMI_MATCH(DMI_SYS_VENDOR, "NCR Corporation"), 95 DMI_MATCH(DMI_PRODUCT_NAME, ""), 96 }, 97 }, 98 { 99 .callback = intel_dmi_reverse_brightness, 100 .ident = "Thundersoft TST178 tablet", 101 /* DMI strings are too generic, also match on BIOS date */ 102 .matches = {DMI_EXACT_MATCH(DMI_BOARD_VENDOR, "AMI Corporation"), 103 DMI_EXACT_MATCH(DMI_BOARD_NAME, "Aptio CRB"), 104 DMI_EXACT_MATCH(DMI_PRODUCT_NAME, "To be filled by O.E.M."), 105 DMI_EXACT_MATCH(DMI_BIOS_DATE, "04/15/2014"), 106 }, 107 }, 108 { } /* terminating entry */ 109 }, 110 .hook = quirk_invert_brightness, 111 }, 112 { 113 .dmi_id_list = &(const struct dmi_system_id[]) { 114 { 115 .callback = intel_dmi_no_pps_backlight, 116 .ident = "Google Lillipup sku524294", 117 .matches = {DMI_EXACT_MATCH(DMI_BOARD_VENDOR, "Google"), 118 DMI_EXACT_MATCH(DMI_BOARD_NAME, "Lindar"), 119 DMI_EXACT_MATCH(DMI_PRODUCT_SKU, "sku524294"), 120 }, 121 }, 122 { 123 .callback = intel_dmi_no_pps_backlight, 124 .ident = "Google Lillipup sku524295", 125 .matches = {DMI_EXACT_MATCH(DMI_BOARD_VENDOR, "Google"), 126 DMI_EXACT_MATCH(DMI_BOARD_NAME, "Lindar"), 127 DMI_EXACT_MATCH(DMI_PRODUCT_SKU, "sku524295"), 128 }, 129 }, 130 { } 131 }, 132 .hook = quirk_no_pps_backlight_power_hook, 133 }, 134 }; 135 136 static struct intel_quirk intel_quirks[] = { 137 /* Lenovo U160 cannot use SSC on LVDS */ 138 { 0x0046, 0x17aa, 0x3920, quirk_ssc_force_disable }, 139 140 /* Sony Vaio Y cannot use SSC on LVDS */ 141 { 0x0046, 0x104d, 0x9076, quirk_ssc_force_disable }, 142 143 /* Acer Aspire 5734Z must invert backlight brightness */ 144 { 0x2a42, 0x1025, 0x0459, quirk_invert_brightness }, 145 146 /* Acer/eMachines G725 */ 147 { 0x2a42, 0x1025, 0x0210, quirk_invert_brightness }, 148 149 /* Acer/eMachines e725 */ 150 { 0x2a42, 0x1025, 0x0212, quirk_invert_brightness }, 151 152 /* Acer/Packard Bell NCL20 */ 153 { 0x2a42, 0x1025, 0x034b, quirk_invert_brightness }, 154 155 /* Acer Aspire 4736Z */ 156 { 0x2a42, 0x1025, 0x0260, quirk_invert_brightness }, 157 158 /* Acer Aspire 5336 */ 159 { 0x2a42, 0x1025, 0x048a, quirk_invert_brightness }, 160 161 /* Acer C720 and C720P Chromebooks (Celeron 2955U) have backlights */ 162 { 0x0a06, 0x1025, 0x0a11, quirk_backlight_present }, 163 164 /* Acer C720 Chromebook (Core i3 4005U) */ 165 { 0x0a16, 0x1025, 0x0a11, quirk_backlight_present }, 166 167 /* Apple Macbook 2,1 (Core 2 T7400) */ 168 { 0x27a2, 0x8086, 0x7270, quirk_backlight_present }, 169 170 /* Apple Macbook 4,1 */ 171 { 0x2a02, 0x106b, 0x00a1, quirk_backlight_present }, 172 173 /* Toshiba CB35 Chromebook (Celeron 2955U) */ 174 { 0x0a06, 0x1179, 0x0a88, quirk_backlight_present }, 175 176 /* HP Chromebook 14 (Celeron 2955U) */ 177 { 0x0a06, 0x103c, 0x21ed, quirk_backlight_present }, 178 179 /* Dell Chromebook 11 */ 180 { 0x0a06, 0x1028, 0x0a35, quirk_backlight_present }, 181 182 /* Dell Chromebook 11 (2015 version) */ 183 { 0x0a16, 0x1028, 0x0a35, quirk_backlight_present }, 184 185 /* Toshiba Satellite P50-C-18C */ 186 { 0x191B, 0x1179, 0xF840, quirk_increase_t12_delay }, 187 188 /* GeminiLake NUC */ 189 { 0x3185, 0x8086, 0x2072, quirk_increase_ddi_disabled_time }, 190 { 0x3184, 0x8086, 0x2072, quirk_increase_ddi_disabled_time }, 191 /* ASRock ITX*/ 192 { 0x3185, 0x1849, 0x2212, quirk_increase_ddi_disabled_time }, 193 { 0x3184, 0x1849, 0x2212, quirk_increase_ddi_disabled_time }, 194 }; 195 196 void intel_init_quirks(struct drm_i915_private *i915) 197 { 198 struct pci_dev *d = to_pci_dev(i915->drm.dev); 199 int i; 200 201 for (i = 0; i < ARRAY_SIZE(intel_quirks); i++) { 202 struct intel_quirk *q = &intel_quirks[i]; 203 204 if (d->device == q->device && 205 (d->subsystem_vendor == q->subsystem_vendor || 206 q->subsystem_vendor == PCI_ANY_ID) && 207 (d->subsystem_device == q->subsystem_device || 208 q->subsystem_device == PCI_ANY_ID)) 209 q->hook(i915); 210 } 211 for (i = 0; i < ARRAY_SIZE(intel_dmi_quirks); i++) { 212 if (dmi_check_system(*intel_dmi_quirks[i].dmi_id_list) != 0) 213 intel_dmi_quirks[i].hook(i915); 214 } 215 } 216