xref: /dflybsd-src/sys/dev/drm/i915/intel_acpi.c (revision 3f2dd94a569761201b5b0a18b2f697f97fe1b9dc)
15d0b1887SFrançois Tigeot /*
25d0b1887SFrançois Tigeot  * Intel ACPI functions
35d0b1887SFrançois Tigeot  *
45d0b1887SFrançois Tigeot  * _DSM related code stolen from nouveau_acpi.c.
55d0b1887SFrançois Tigeot  */
65d0b1887SFrançois Tigeot #include <linux/pci.h>
7bf017597SFrançois Tigeot #include <linux/acpi.h>
85d0b1887SFrançois Tigeot #include <drm/drmP.h>
95d0b1887SFrançois Tigeot #include "i915_drv.h"
105d0b1887SFrançois Tigeot 
115d0b1887SFrançois Tigeot #define INTEL_DSM_REVISION_ID 1 /* For Calpella anyway... */
125d0b1887SFrançois Tigeot #define INTEL_DSM_FN_PLATFORM_MUX_INFO 1 /* No args */
135d0b1887SFrançois Tigeot 
145d0b1887SFrançois Tigeot #if 0
155d0b1887SFrançois Tigeot static struct intel_dsm_priv {
165d0b1887SFrançois Tigeot 	acpi_handle dhandle;
175d0b1887SFrançois Tigeot } intel_dsm_priv;
185d0b1887SFrançois Tigeot 
19*3f2dd94aSFrançois Tigeot static const guid_t intel_dsm_guid =
20*3f2dd94aSFrançois Tigeot 	GUID_INIT(0x7ed873d3, 0xc2d0, 0x4e4f,
21*3f2dd94aSFrançois Tigeot 		  0xa8, 0x54, 0x0f, 0x13, 0x17, 0xb0, 0x1c, 0x2c);
225d0b1887SFrançois Tigeot 
235d0b1887SFrançois Tigeot static char *intel_dsm_port_name(u8 id)
245d0b1887SFrançois Tigeot {
255d0b1887SFrançois Tigeot 	switch (id) {
265d0b1887SFrançois Tigeot 	case 0:
275d0b1887SFrançois Tigeot 		return "Reserved";
285d0b1887SFrançois Tigeot 	case 1:
295d0b1887SFrançois Tigeot 		return "Analog VGA";
305d0b1887SFrançois Tigeot 	case 2:
315d0b1887SFrançois Tigeot 		return "LVDS";
325d0b1887SFrançois Tigeot 	case 3:
335d0b1887SFrançois Tigeot 		return "Reserved";
345d0b1887SFrançois Tigeot 	case 4:
355d0b1887SFrançois Tigeot 		return "HDMI/DVI_B";
365d0b1887SFrançois Tigeot 	case 5:
375d0b1887SFrançois Tigeot 		return "HDMI/DVI_C";
385d0b1887SFrançois Tigeot 	case 6:
395d0b1887SFrançois Tigeot 		return "HDMI/DVI_D";
405d0b1887SFrançois Tigeot 	case 7:
415d0b1887SFrançois Tigeot 		return "DisplayPort_A";
425d0b1887SFrançois Tigeot 	case 8:
435d0b1887SFrançois Tigeot 		return "DisplayPort_B";
445d0b1887SFrançois Tigeot 	case 9:
455d0b1887SFrançois Tigeot 		return "DisplayPort_C";
465d0b1887SFrançois Tigeot 	case 0xa:
475d0b1887SFrançois Tigeot 		return "DisplayPort_D";
485d0b1887SFrançois Tigeot 	case 0xb:
495d0b1887SFrançois Tigeot 	case 0xc:
505d0b1887SFrançois Tigeot 	case 0xd:
515d0b1887SFrançois Tigeot 		return "Reserved";
525d0b1887SFrançois Tigeot 	case 0xe:
535d0b1887SFrançois Tigeot 		return "WiDi";
545d0b1887SFrançois Tigeot 	default:
555d0b1887SFrançois Tigeot 		return "bad type";
565d0b1887SFrançois Tigeot 	}
575d0b1887SFrançois Tigeot }
585d0b1887SFrançois Tigeot 
595d0b1887SFrançois Tigeot static char *intel_dsm_mux_type(u8 type)
605d0b1887SFrançois Tigeot {
615d0b1887SFrançois Tigeot 	switch (type) {
625d0b1887SFrançois Tigeot 	case 0:
635d0b1887SFrançois Tigeot 		return "unknown";
645d0b1887SFrançois Tigeot 	case 1:
655d0b1887SFrançois Tigeot 		return "No MUX, iGPU only";
665d0b1887SFrançois Tigeot 	case 2:
675d0b1887SFrançois Tigeot 		return "No MUX, dGPU only";
685d0b1887SFrançois Tigeot 	case 3:
695d0b1887SFrançois Tigeot 		return "MUXed between iGPU and dGPU";
705d0b1887SFrançois Tigeot 	default:
715d0b1887SFrançois Tigeot 		return "bad type";
725d0b1887SFrançois Tigeot 	}
735d0b1887SFrançois Tigeot }
745d0b1887SFrançois Tigeot 
755d0b1887SFrançois Tigeot static void intel_dsm_platform_mux_info(void)
765d0b1887SFrançois Tigeot {
779edbd4a0SFrançois Tigeot 	int i;
789edbd4a0SFrançois Tigeot 	union acpi_object *pkg, *connector_count;
795d0b1887SFrançois Tigeot 
80*3f2dd94aSFrançois Tigeot 	pkg = acpi_evaluate_dsm_typed(intel_dsm_priv.dhandle, &intel_dsm_guid,
819edbd4a0SFrançois Tigeot 			INTEL_DSM_REVISION_ID, INTEL_DSM_FN_PLATFORM_MUX_INFO,
829edbd4a0SFrançois Tigeot 			NULL, ACPI_TYPE_PACKAGE);
839edbd4a0SFrançois Tigeot 	if (!pkg) {
849edbd4a0SFrançois Tigeot 		DRM_DEBUG_DRIVER("failed to evaluate _DSM\n");
859edbd4a0SFrançois Tigeot 		return;
865d0b1887SFrançois Tigeot 	}
875d0b1887SFrançois Tigeot 
889edbd4a0SFrançois Tigeot 	connector_count = &pkg->package.elements[0];
895d0b1887SFrançois Tigeot 	DRM_DEBUG_DRIVER("MUX info connectors: %lld\n",
905d0b1887SFrançois Tigeot 		  (unsigned long long)connector_count->integer.value);
915d0b1887SFrançois Tigeot 	for (i = 1; i < pkg->package.count; i++) {
925d0b1887SFrançois Tigeot 		union acpi_object *obj = &pkg->package.elements[i];
939edbd4a0SFrançois Tigeot 		union acpi_object *connector_id = &obj->package.elements[0];
945d0b1887SFrançois Tigeot 		union acpi_object *info = &obj->package.elements[1];
955d0b1887SFrançois Tigeot 		DRM_DEBUG_DRIVER("Connector id: 0x%016llx\n",
965d0b1887SFrançois Tigeot 			  (unsigned long long)connector_id->integer.value);
975d0b1887SFrançois Tigeot 		DRM_DEBUG_DRIVER("  port id: %s\n",
985d0b1887SFrançois Tigeot 		       intel_dsm_port_name(info->buffer.pointer[0]));
995d0b1887SFrançois Tigeot 		DRM_DEBUG_DRIVER("  display mux info: %s\n",
1005d0b1887SFrançois Tigeot 		       intel_dsm_mux_type(info->buffer.pointer[1]));
1015d0b1887SFrançois Tigeot 		DRM_DEBUG_DRIVER("  aux/dc mux info: %s\n",
1025d0b1887SFrançois Tigeot 		       intel_dsm_mux_type(info->buffer.pointer[2]));
1035d0b1887SFrançois Tigeot 		DRM_DEBUG_DRIVER("  hpd mux info: %s\n",
1045d0b1887SFrançois Tigeot 		       intel_dsm_mux_type(info->buffer.pointer[3]));
1055d0b1887SFrançois Tigeot 	}
1065d0b1887SFrançois Tigeot 
1079edbd4a0SFrançois Tigeot 	ACPI_FREE(pkg);
1085d0b1887SFrançois Tigeot }
1095d0b1887SFrançois Tigeot 
1105d0b1887SFrançois Tigeot static bool intel_dsm_pci_probe(struct pci_dev *pdev)
1115d0b1887SFrançois Tigeot {
1129edbd4a0SFrançois Tigeot 	acpi_handle dhandle;
1135d0b1887SFrançois Tigeot 
1149edbd4a0SFrançois Tigeot 	dhandle = ACPI_HANDLE(&pdev->dev);
1155d0b1887SFrançois Tigeot 	if (!dhandle)
1165d0b1887SFrançois Tigeot 		return false;
1175d0b1887SFrançois Tigeot 
118*3f2dd94aSFrançois Tigeot 	if (!acpi_check_dsm(dhandle, &intel_dsm_guid, INTEL_DSM_REVISION_ID,
1199edbd4a0SFrançois Tigeot 			    1 << INTEL_DSM_FN_PLATFORM_MUX_INFO)) {
1205d0b1887SFrançois Tigeot 		DRM_DEBUG_KMS("no _DSM method for intel device\n");
1215d0b1887SFrançois Tigeot 		return false;
1225d0b1887SFrançois Tigeot 	}
1235d0b1887SFrançois Tigeot 
1245d0b1887SFrançois Tigeot 	intel_dsm_priv.dhandle = dhandle;
1255d0b1887SFrançois Tigeot 	intel_dsm_platform_mux_info();
1269edbd4a0SFrançois Tigeot 
1275d0b1887SFrançois Tigeot 	return true;
1285d0b1887SFrançois Tigeot }
1295d0b1887SFrançois Tigeot 
1305d0b1887SFrançois Tigeot static bool intel_dsm_detect(void)
1315d0b1887SFrançois Tigeot {
1325d0b1887SFrançois Tigeot 	char acpi_method_name[255] = { 0 };
1335d0b1887SFrançois Tigeot 	struct acpi_buffer buffer = {sizeof(acpi_method_name), acpi_method_name};
1345d0b1887SFrançois Tigeot 	struct pci_dev *pdev = NULL;
1355d0b1887SFrançois Tigeot 	bool has_dsm = false;
1365d0b1887SFrançois Tigeot 	int vga_count = 0;
1375d0b1887SFrançois Tigeot 
1385d0b1887SFrançois Tigeot 	while ((pdev = pci_get_class(PCI_CLASS_DISPLAY_VGA << 8, pdev)) != NULL) {
1395d0b1887SFrançois Tigeot 		vga_count++;
1405d0b1887SFrançois Tigeot 		has_dsm |= intel_dsm_pci_probe(pdev);
1415d0b1887SFrançois Tigeot 	}
1425d0b1887SFrançois Tigeot 
1435d0b1887SFrançois Tigeot 	if (vga_count == 2 && has_dsm) {
1445d0b1887SFrançois Tigeot 		acpi_get_name(intel_dsm_priv.dhandle, ACPI_FULL_PATHNAME, &buffer);
145352ff8bdSFrançois Tigeot 		DRM_DEBUG_DRIVER("vga_switcheroo: detected DSM switching method %s handle\n",
1465d0b1887SFrançois Tigeot 				 acpi_method_name);
1475d0b1887SFrançois Tigeot 		return true;
1485d0b1887SFrançois Tigeot 	}
1495d0b1887SFrançois Tigeot 
1505d0b1887SFrançois Tigeot 	return false;
1515d0b1887SFrançois Tigeot }
1525d0b1887SFrançois Tigeot 
1535d0b1887SFrançois Tigeot void intel_register_dsm_handler(void)
1545d0b1887SFrançois Tigeot {
1555d0b1887SFrançois Tigeot 	if (!intel_dsm_detect())
1565d0b1887SFrançois Tigeot 		return;
1575d0b1887SFrançois Tigeot }
1585d0b1887SFrançois Tigeot #endif
1595d0b1887SFrançois Tigeot 
intel_unregister_dsm_handler(void)1605d0b1887SFrançois Tigeot void intel_unregister_dsm_handler(void)
1615d0b1887SFrançois Tigeot {
1625d0b1887SFrançois Tigeot }
163