1 // SPDX-License-Identifier: GPL-2.0 2 /* 3 * Intel ACPI functions 4 * 5 * _DSM related code stolen from nouveau_acpi.c. 6 */ 7 8 #include <linux/pci.h> 9 #include <linux/acpi.h> 10 11 #include "i915_drv.h" 12 #include "intel_acpi.h" 13 #include "intel_display_types.h" 14 15 #define INTEL_DSM_REVISION_ID 1 /* For Calpella anyway... */ 16 #define INTEL_DSM_FN_PLATFORM_MUX_INFO 1 /* No args */ 17 18 static const guid_t intel_dsm_guid = 19 GUID_INIT(0x7ed873d3, 0xc2d0, 0x4e4f, 20 0xa8, 0x54, 0x0f, 0x13, 0x17, 0xb0, 0x1c, 0x2c); 21 22 #define INTEL_DSM_FN_GET_BIOS_DATA_FUNCS_SUPPORTED 0 /* No args */ 23 24 static const guid_t intel_dsm_guid2 = 25 GUID_INIT(0x3e5b41c6, 0xeb1d, 0x4260, 26 0x9d, 0x15, 0xc7, 0x1f, 0xba, 0xda, 0xe4, 0x14); 27 28 static char *intel_dsm_port_name(u8 id) 29 { 30 switch (id) { 31 case 0: 32 return "Reserved"; 33 case 1: 34 return "Analog VGA"; 35 case 2: 36 return "LVDS"; 37 case 3: 38 return "Reserved"; 39 case 4: 40 return "HDMI/DVI_B"; 41 case 5: 42 return "HDMI/DVI_C"; 43 case 6: 44 return "HDMI/DVI_D"; 45 case 7: 46 return "DisplayPort_A"; 47 case 8: 48 return "DisplayPort_B"; 49 case 9: 50 return "DisplayPort_C"; 51 case 0xa: 52 return "DisplayPort_D"; 53 case 0xb: 54 case 0xc: 55 case 0xd: 56 return "Reserved"; 57 case 0xe: 58 return "WiDi"; 59 default: 60 return "bad type"; 61 } 62 } 63 64 static char *intel_dsm_mux_type(u8 type) 65 { 66 switch (type) { 67 case 0: 68 return "unknown"; 69 case 1: 70 return "No MUX, iGPU only"; 71 case 2: 72 return "No MUX, dGPU only"; 73 case 3: 74 return "MUXed between iGPU and dGPU"; 75 default: 76 return "bad type"; 77 } 78 } 79 80 static void intel_dsm_platform_mux_info(acpi_handle dhandle) 81 { 82 int i; 83 union acpi_object *pkg, *connector_count; 84 85 pkg = acpi_evaluate_dsm_typed(dhandle, &intel_dsm_guid, 86 INTEL_DSM_REVISION_ID, INTEL_DSM_FN_PLATFORM_MUX_INFO, 87 NULL, ACPI_TYPE_PACKAGE); 88 if (!pkg) { 89 DRM_DEBUG_DRIVER("failed to evaluate _DSM\n"); 90 return; 91 } 92 93 if (!pkg->package.count) { 94 DRM_DEBUG_DRIVER("no connection in _DSM\n"); 95 return; 96 } 97 98 connector_count = &pkg->package.elements[0]; 99 DRM_DEBUG_DRIVER("MUX info connectors: %lld\n", 100 (unsigned long long)connector_count->integer.value); 101 for (i = 1; i < pkg->package.count; i++) { 102 union acpi_object *obj = &pkg->package.elements[i]; 103 union acpi_object *connector_id; 104 union acpi_object *info; 105 106 if (obj->type != ACPI_TYPE_PACKAGE || obj->package.count < 2) { 107 DRM_DEBUG_DRIVER("Invalid object for MUX #%d\n", i); 108 continue; 109 } 110 111 connector_id = &obj->package.elements[0]; 112 info = &obj->package.elements[1]; 113 if (info->type != ACPI_TYPE_BUFFER || info->buffer.length < 4) { 114 DRM_DEBUG_DRIVER("Invalid info for MUX obj #%d\n", i); 115 continue; 116 } 117 118 DRM_DEBUG_DRIVER("Connector id: 0x%016llx\n", 119 (unsigned long long)connector_id->integer.value); 120 DRM_DEBUG_DRIVER(" port id: %s\n", 121 intel_dsm_port_name(info->buffer.pointer[0])); 122 DRM_DEBUG_DRIVER(" display mux info: %s\n", 123 intel_dsm_mux_type(info->buffer.pointer[1])); 124 DRM_DEBUG_DRIVER(" aux/dc mux info: %s\n", 125 intel_dsm_mux_type(info->buffer.pointer[2])); 126 DRM_DEBUG_DRIVER(" hpd mux info: %s\n", 127 intel_dsm_mux_type(info->buffer.pointer[3])); 128 } 129 130 ACPI_FREE(pkg); 131 } 132 133 static acpi_handle intel_dsm_pci_probe(struct pci_dev *pdev) 134 { 135 acpi_handle dhandle; 136 137 dhandle = ACPI_HANDLE(&pdev->dev); 138 if (!dhandle) 139 return NULL; 140 141 if (!acpi_check_dsm(dhandle, &intel_dsm_guid, INTEL_DSM_REVISION_ID, 142 1 << INTEL_DSM_FN_PLATFORM_MUX_INFO)) { 143 DRM_DEBUG_KMS("no _DSM method for intel device\n"); 144 return NULL; 145 } 146 147 intel_dsm_platform_mux_info(dhandle); 148 149 return dhandle; 150 } 151 152 static bool intel_dsm_detect(void) 153 { 154 acpi_handle dhandle = NULL; 155 char acpi_method_name[255] = { 0 }; 156 struct acpi_buffer buffer = {sizeof(acpi_method_name), acpi_method_name}; 157 struct pci_dev *pdev = NULL; 158 int vga_count = 0; 159 160 while ((pdev = pci_get_class(PCI_CLASS_DISPLAY_VGA << 8, pdev)) != NULL) { 161 vga_count++; 162 dhandle = intel_dsm_pci_probe(pdev) ?: dhandle; 163 } 164 165 if (vga_count == 2 && dhandle) { 166 acpi_get_name(dhandle, ACPI_FULL_PATHNAME, &buffer); 167 DRM_DEBUG_DRIVER("vga_switcheroo: detected DSM switching method %s handle\n", 168 acpi_method_name); 169 return true; 170 } 171 172 return false; 173 } 174 175 void intel_register_dsm_handler(void) 176 { 177 if (!intel_dsm_detect()) 178 return; 179 } 180 181 void intel_unregister_dsm_handler(void) 182 { 183 } 184 185 void intel_dsm_get_bios_data_funcs_supported(struct drm_i915_private *i915) 186 { 187 struct pci_dev *pdev = to_pci_dev(i915->drm.dev); 188 acpi_handle dhandle; 189 union acpi_object *obj; 190 191 dhandle = ACPI_HANDLE(&pdev->dev); 192 if (!dhandle) 193 return; 194 195 obj = acpi_evaluate_dsm(dhandle, &intel_dsm_guid2, INTEL_DSM_REVISION_ID, 196 INTEL_DSM_FN_GET_BIOS_DATA_FUNCS_SUPPORTED, NULL); 197 if (obj) 198 ACPI_FREE(obj); 199 } 200 201 /* 202 * ACPI Specification, Revision 5.0, Appendix B.3.2 _DOD (Enumerate All Devices 203 * Attached to the Display Adapter). 204 */ 205 #define ACPI_DISPLAY_INDEX_SHIFT 0 206 #define ACPI_DISPLAY_INDEX_MASK (0xf << 0) 207 #define ACPI_DISPLAY_PORT_ATTACHMENT_SHIFT 4 208 #define ACPI_DISPLAY_PORT_ATTACHMENT_MASK (0xf << 4) 209 #define ACPI_DISPLAY_TYPE_SHIFT 8 210 #define ACPI_DISPLAY_TYPE_MASK (0xf << 8) 211 #define ACPI_DISPLAY_TYPE_OTHER (0 << 8) 212 #define ACPI_DISPLAY_TYPE_VGA (1 << 8) 213 #define ACPI_DISPLAY_TYPE_TV (2 << 8) 214 #define ACPI_DISPLAY_TYPE_EXTERNAL_DIGITAL (3 << 8) 215 #define ACPI_DISPLAY_TYPE_INTERNAL_DIGITAL (4 << 8) 216 #define ACPI_VENDOR_SPECIFIC_SHIFT 12 217 #define ACPI_VENDOR_SPECIFIC_MASK (0xf << 12) 218 #define ACPI_BIOS_CAN_DETECT (1 << 16) 219 #define ACPI_DEPENDS_ON_VGA (1 << 17) 220 #define ACPI_PIPE_ID_SHIFT 18 221 #define ACPI_PIPE_ID_MASK (7 << 18) 222 #define ACPI_DEVICE_ID_SCHEME (1ULL << 31) 223 224 static u32 acpi_display_type(struct intel_connector *connector) 225 { 226 u32 display_type; 227 228 switch (connector->base.connector_type) { 229 case DRM_MODE_CONNECTOR_VGA: 230 case DRM_MODE_CONNECTOR_DVIA: 231 display_type = ACPI_DISPLAY_TYPE_VGA; 232 break; 233 case DRM_MODE_CONNECTOR_Composite: 234 case DRM_MODE_CONNECTOR_SVIDEO: 235 case DRM_MODE_CONNECTOR_Component: 236 case DRM_MODE_CONNECTOR_9PinDIN: 237 case DRM_MODE_CONNECTOR_TV: 238 display_type = ACPI_DISPLAY_TYPE_TV; 239 break; 240 case DRM_MODE_CONNECTOR_DVII: 241 case DRM_MODE_CONNECTOR_DVID: 242 case DRM_MODE_CONNECTOR_DisplayPort: 243 case DRM_MODE_CONNECTOR_HDMIA: 244 case DRM_MODE_CONNECTOR_HDMIB: 245 display_type = ACPI_DISPLAY_TYPE_EXTERNAL_DIGITAL; 246 break; 247 case DRM_MODE_CONNECTOR_LVDS: 248 case DRM_MODE_CONNECTOR_eDP: 249 case DRM_MODE_CONNECTOR_DSI: 250 display_type = ACPI_DISPLAY_TYPE_INTERNAL_DIGITAL; 251 break; 252 case DRM_MODE_CONNECTOR_Unknown: 253 case DRM_MODE_CONNECTOR_VIRTUAL: 254 display_type = ACPI_DISPLAY_TYPE_OTHER; 255 break; 256 default: 257 MISSING_CASE(connector->base.connector_type); 258 display_type = ACPI_DISPLAY_TYPE_OTHER; 259 break; 260 } 261 262 return display_type; 263 } 264 265 void intel_acpi_device_id_update(struct drm_i915_private *dev_priv) 266 { 267 struct drm_device *drm_dev = &dev_priv->drm; 268 struct intel_connector *connector; 269 struct drm_connector_list_iter conn_iter; 270 u8 display_index[16] = {}; 271 272 /* Populate the ACPI IDs for all connectors for a given drm_device */ 273 drm_connector_list_iter_begin(drm_dev, &conn_iter); 274 for_each_intel_connector_iter(connector, &conn_iter) { 275 u32 device_id, type; 276 277 device_id = acpi_display_type(connector); 278 279 /* Use display type specific display index. */ 280 type = (device_id & ACPI_DISPLAY_TYPE_MASK) 281 >> ACPI_DISPLAY_TYPE_SHIFT; 282 device_id |= display_index[type]++ << ACPI_DISPLAY_INDEX_SHIFT; 283 284 connector->acpi_device_id = device_id; 285 } 286 drm_connector_list_iter_end(&conn_iter); 287 } 288 289 /* NOTE: The connector order must be final before this is called. */ 290 void intel_acpi_assign_connector_fwnodes(struct drm_i915_private *i915) 291 { 292 struct drm_connector_list_iter conn_iter; 293 struct drm_device *drm_dev = &i915->drm; 294 struct fwnode_handle *fwnode = NULL; 295 struct drm_connector *connector; 296 struct acpi_device *adev; 297 298 drm_connector_list_iter_begin(drm_dev, &conn_iter); 299 drm_for_each_connector_iter(connector, &conn_iter) { 300 /* Always getting the next, even when the last was not used. */ 301 fwnode = device_get_next_child_node(drm_dev->dev, fwnode); 302 if (!fwnode) 303 break; 304 305 switch (connector->connector_type) { 306 case DRM_MODE_CONNECTOR_LVDS: 307 case DRM_MODE_CONNECTOR_eDP: 308 case DRM_MODE_CONNECTOR_DSI: 309 /* 310 * Integrated displays have a specific address 0x1f on 311 * most Intel platforms, but not on all of them. 312 */ 313 adev = acpi_find_child_device(ACPI_COMPANION(drm_dev->dev), 314 0x1f, 0); 315 if (adev) { 316 connector->fwnode = 317 fwnode_handle_get(acpi_fwnode_handle(adev)); 318 break; 319 } 320 fallthrough; 321 default: 322 connector->fwnode = fwnode_handle_get(fwnode); 323 break; 324 } 325 } 326 drm_connector_list_iter_end(&conn_iter); 327 /* 328 * device_get_next_child_node() takes a reference on the fwnode, if 329 * we stopped iterating because we are out of connectors we need to 330 * put this, otherwise fwnode is NULL and the put is a no-op. 331 */ 332 fwnode_handle_put(fwnode); 333 } 334