xref: /dflybsd-src/sys/dev/drm/i915/intel_acpi.c (revision 9edbd4a07c3138f5c4f076f77de5d722fcc606cc)
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>
75d0b1887SFrançois Tigeot 
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 
195d0b1887SFrançois Tigeot static const u8 intel_dsm_guid[] = {
205d0b1887SFrançois Tigeot 	0xd3, 0x73, 0xd8, 0x7e,
215d0b1887SFrançois Tigeot 	0xd0, 0xc2,
225d0b1887SFrançois Tigeot 	0x4f, 0x4e,
235d0b1887SFrançois Tigeot 	0xa8, 0x54,
245d0b1887SFrançois Tigeot 	0x0f, 0x13, 0x17, 0xb0, 0x1c, 0x2c
255d0b1887SFrançois Tigeot };
265d0b1887SFrançois Tigeot 
275d0b1887SFrançois Tigeot static char *intel_dsm_port_name(u8 id)
285d0b1887SFrançois Tigeot {
295d0b1887SFrançois Tigeot 	switch (id) {
305d0b1887SFrançois Tigeot 	case 0:
315d0b1887SFrançois Tigeot 		return "Reserved";
325d0b1887SFrançois Tigeot 	case 1:
335d0b1887SFrançois Tigeot 		return "Analog VGA";
345d0b1887SFrançois Tigeot 	case 2:
355d0b1887SFrançois Tigeot 		return "LVDS";
365d0b1887SFrançois Tigeot 	case 3:
375d0b1887SFrançois Tigeot 		return "Reserved";
385d0b1887SFrançois Tigeot 	case 4:
395d0b1887SFrançois Tigeot 		return "HDMI/DVI_B";
405d0b1887SFrançois Tigeot 	case 5:
415d0b1887SFrançois Tigeot 		return "HDMI/DVI_C";
425d0b1887SFrançois Tigeot 	case 6:
435d0b1887SFrançois Tigeot 		return "HDMI/DVI_D";
445d0b1887SFrançois Tigeot 	case 7:
455d0b1887SFrançois Tigeot 		return "DisplayPort_A";
465d0b1887SFrançois Tigeot 	case 8:
475d0b1887SFrançois Tigeot 		return "DisplayPort_B";
485d0b1887SFrançois Tigeot 	case 9:
495d0b1887SFrançois Tigeot 		return "DisplayPort_C";
505d0b1887SFrançois Tigeot 	case 0xa:
515d0b1887SFrançois Tigeot 		return "DisplayPort_D";
525d0b1887SFrançois Tigeot 	case 0xb:
535d0b1887SFrançois Tigeot 	case 0xc:
545d0b1887SFrançois Tigeot 	case 0xd:
555d0b1887SFrançois Tigeot 		return "Reserved";
565d0b1887SFrançois Tigeot 	case 0xe:
575d0b1887SFrançois Tigeot 		return "WiDi";
585d0b1887SFrançois Tigeot 	default:
595d0b1887SFrançois Tigeot 		return "bad type";
605d0b1887SFrançois Tigeot 	}
615d0b1887SFrançois Tigeot }
625d0b1887SFrançois Tigeot 
635d0b1887SFrançois Tigeot static char *intel_dsm_mux_type(u8 type)
645d0b1887SFrançois Tigeot {
655d0b1887SFrançois Tigeot 	switch (type) {
665d0b1887SFrançois Tigeot 	case 0:
675d0b1887SFrançois Tigeot 		return "unknown";
685d0b1887SFrançois Tigeot 	case 1:
695d0b1887SFrançois Tigeot 		return "No MUX, iGPU only";
705d0b1887SFrançois Tigeot 	case 2:
715d0b1887SFrançois Tigeot 		return "No MUX, dGPU only";
725d0b1887SFrançois Tigeot 	case 3:
735d0b1887SFrançois Tigeot 		return "MUXed between iGPU and dGPU";
745d0b1887SFrançois Tigeot 	default:
755d0b1887SFrançois Tigeot 		return "bad type";
765d0b1887SFrançois Tigeot 	}
775d0b1887SFrançois Tigeot }
785d0b1887SFrançois Tigeot 
795d0b1887SFrançois Tigeot static void intel_dsm_platform_mux_info(void)
805d0b1887SFrançois Tigeot {
81*9edbd4a0SFrançois Tigeot 	int i;
82*9edbd4a0SFrançois Tigeot 	union acpi_object *pkg, *connector_count;
835d0b1887SFrançois Tigeot 
84*9edbd4a0SFrançois Tigeot 	pkg = acpi_evaluate_dsm_typed(intel_dsm_priv.dhandle, intel_dsm_guid,
85*9edbd4a0SFrançois Tigeot 			INTEL_DSM_REVISION_ID, INTEL_DSM_FN_PLATFORM_MUX_INFO,
86*9edbd4a0SFrançois Tigeot 			NULL, ACPI_TYPE_PACKAGE);
87*9edbd4a0SFrançois Tigeot 	if (!pkg) {
88*9edbd4a0SFrançois Tigeot 		DRM_DEBUG_DRIVER("failed to evaluate _DSM\n");
89*9edbd4a0SFrançois Tigeot 		return;
905d0b1887SFrançois Tigeot 	}
915d0b1887SFrançois Tigeot 
92*9edbd4a0SFrançois Tigeot 	connector_count = &pkg->package.elements[0];
935d0b1887SFrançois Tigeot 	DRM_DEBUG_DRIVER("MUX info connectors: %lld\n",
945d0b1887SFrançois Tigeot 		  (unsigned long long)connector_count->integer.value);
955d0b1887SFrançois Tigeot 	for (i = 1; i < pkg->package.count; i++) {
965d0b1887SFrançois Tigeot 		union acpi_object *obj = &pkg->package.elements[i];
97*9edbd4a0SFrançois Tigeot 		union acpi_object *connector_id = &obj->package.elements[0];
985d0b1887SFrançois Tigeot 		union acpi_object *info = &obj->package.elements[1];
995d0b1887SFrançois Tigeot 		DRM_DEBUG_DRIVER("Connector id: 0x%016llx\n",
1005d0b1887SFrançois Tigeot 			  (unsigned long long)connector_id->integer.value);
1015d0b1887SFrançois Tigeot 		DRM_DEBUG_DRIVER("  port id: %s\n",
1025d0b1887SFrançois Tigeot 		       intel_dsm_port_name(info->buffer.pointer[0]));
1035d0b1887SFrançois Tigeot 		DRM_DEBUG_DRIVER("  display mux info: %s\n",
1045d0b1887SFrançois Tigeot 		       intel_dsm_mux_type(info->buffer.pointer[1]));
1055d0b1887SFrançois Tigeot 		DRM_DEBUG_DRIVER("  aux/dc mux info: %s\n",
1065d0b1887SFrançois Tigeot 		       intel_dsm_mux_type(info->buffer.pointer[2]));
1075d0b1887SFrançois Tigeot 		DRM_DEBUG_DRIVER("  hpd mux info: %s\n",
1085d0b1887SFrançois Tigeot 		       intel_dsm_mux_type(info->buffer.pointer[3]));
1095d0b1887SFrançois Tigeot 	}
1105d0b1887SFrançois Tigeot 
111*9edbd4a0SFrançois Tigeot 	ACPI_FREE(pkg);
1125d0b1887SFrançois Tigeot }
1135d0b1887SFrançois Tigeot 
1145d0b1887SFrançois Tigeot static bool intel_dsm_pci_probe(struct pci_dev *pdev)
1155d0b1887SFrançois Tigeot {
116*9edbd4a0SFrançois Tigeot 	acpi_handle dhandle;
1175d0b1887SFrançois Tigeot 
118*9edbd4a0SFrançois Tigeot 	dhandle = ACPI_HANDLE(&pdev->dev);
1195d0b1887SFrançois Tigeot 	if (!dhandle)
1205d0b1887SFrançois Tigeot 		return false;
1215d0b1887SFrançois Tigeot 
122*9edbd4a0SFrançois Tigeot 	if (!acpi_check_dsm(dhandle, intel_dsm_guid, INTEL_DSM_REVISION_ID,
123*9edbd4a0SFrançois Tigeot 			    1 << INTEL_DSM_FN_PLATFORM_MUX_INFO)) {
1245d0b1887SFrançois Tigeot 		DRM_DEBUG_KMS("no _DSM method for intel device\n");
1255d0b1887SFrançois Tigeot 		return false;
1265d0b1887SFrançois Tigeot 	}
1275d0b1887SFrançois Tigeot 
1285d0b1887SFrançois Tigeot 	intel_dsm_priv.dhandle = dhandle;
1295d0b1887SFrançois Tigeot 	intel_dsm_platform_mux_info();
130*9edbd4a0SFrançois Tigeot 
1315d0b1887SFrançois Tigeot 	return true;
1325d0b1887SFrançois Tigeot }
1335d0b1887SFrançois Tigeot 
1345d0b1887SFrançois Tigeot static bool intel_dsm_detect(void)
1355d0b1887SFrançois Tigeot {
1365d0b1887SFrançois Tigeot 	char acpi_method_name[255] = { 0 };
1375d0b1887SFrançois Tigeot 	struct acpi_buffer buffer = {sizeof(acpi_method_name), acpi_method_name};
1385d0b1887SFrançois Tigeot 	struct pci_dev *pdev = NULL;
1395d0b1887SFrançois Tigeot 	bool has_dsm = false;
1405d0b1887SFrançois Tigeot 	int vga_count = 0;
1415d0b1887SFrançois Tigeot 
1425d0b1887SFrançois Tigeot 	while ((pdev = pci_get_class(PCI_CLASS_DISPLAY_VGA << 8, pdev)) != NULL) {
1435d0b1887SFrançois Tigeot 		vga_count++;
1445d0b1887SFrançois Tigeot 		has_dsm |= intel_dsm_pci_probe(pdev);
1455d0b1887SFrançois Tigeot 	}
1465d0b1887SFrançois Tigeot 
1475d0b1887SFrançois Tigeot 	if (vga_count == 2 && has_dsm) {
1485d0b1887SFrançois Tigeot 		acpi_get_name(intel_dsm_priv.dhandle, ACPI_FULL_PATHNAME, &buffer);
1495d0b1887SFrançois Tigeot 		DRM_DEBUG_DRIVER("VGA switcheroo: detected DSM switching method %s handle\n",
1505d0b1887SFrançois Tigeot 				 acpi_method_name);
1515d0b1887SFrançois Tigeot 		return true;
1525d0b1887SFrançois Tigeot 	}
1535d0b1887SFrançois Tigeot 
1545d0b1887SFrançois Tigeot 	return false;
1555d0b1887SFrançois Tigeot }
1565d0b1887SFrançois Tigeot 
1575d0b1887SFrançois Tigeot void intel_register_dsm_handler(void)
1585d0b1887SFrançois Tigeot {
1595d0b1887SFrançois Tigeot 	if (!intel_dsm_detect())
1605d0b1887SFrançois Tigeot 		return;
1615d0b1887SFrançois Tigeot }
1625d0b1887SFrançois Tigeot #endif
1635d0b1887SFrançois Tigeot 
1645d0b1887SFrançois Tigeot void intel_unregister_dsm_handler(void)
1655d0b1887SFrançois Tigeot {
1665d0b1887SFrançois Tigeot }
167