]> Pileus Git - ~andy/linux/blobdiff - drivers/gpu/drm/nouveau/nouveau_acpi.c
Merge branch 'drm-next' of git://people.freedesktop.org/~airlied/linux
[~andy/linux] / drivers / gpu / drm / nouveau / nouveau_acpi.c
index ba0183fb84f3b871a4815552021174e870f780e8..4ef83df2b246fb335dc8ce05bafead80ed7ac180 100644 (file)
@@ -1,15 +1,10 @@
 #include <linux/pci.h>
 #include <linux/acpi.h>
 #include <linux/slab.h>
-#include <acpi/acpi_drivers.h>
-#include <acpi/acpi_bus.h>
-#include <acpi/video.h>
-#include <acpi/acpi.h>
 #include <linux/mxm-wmi.h>
-
 #include <linux/vga_switcheroo.h>
-
 #include <drm/drm_edid.h>
+#include <acpi/video.h>
 
 #include "nouveau_drm.h"
 #include "nouveau_acpi.h"
@@ -66,6 +61,7 @@ bool nouveau_is_v1_dsm(void) {
 #define NOUVEAU_DSM_HAS_MUX 0x1
 #define NOUVEAU_DSM_HAS_OPT 0x2
 
+#ifdef CONFIG_VGA_SWITCHEROO
 static const char nouveau_dsm_muid[] = {
        0xA0, 0xA0, 0x95, 0x9D, 0x60, 0x00, 0x48, 0x4D,
        0xB3, 0x4D, 0x7E, 0x5F, 0xEA, 0x12, 0x9F, 0xD4,
@@ -78,124 +74,66 @@ static const char nouveau_op_dsm_muid[] = {
 
 static int nouveau_optimus_dsm(acpi_handle handle, int func, int arg, uint32_t *result)
 {
-       struct acpi_buffer output = { ACPI_ALLOCATE_BUFFER, NULL };
-       struct acpi_object_list input;
-       union acpi_object params[4];
+       int i;
        union acpi_object *obj;
-       int i, err;
        char args_buff[4];
+       union acpi_object argv4 = {
+               .buffer.type = ACPI_TYPE_BUFFER,
+               .buffer.length = 4,
+               .buffer.pointer = args_buff
+       };
 
-       input.count = 4;
-       input.pointer = params;
-       params[0].type = ACPI_TYPE_BUFFER;
-       params[0].buffer.length = sizeof(nouveau_op_dsm_muid);
-       params[0].buffer.pointer = (char *)nouveau_op_dsm_muid;
-       params[1].type = ACPI_TYPE_INTEGER;
-       params[1].integer.value = 0x00000100;
-       params[2].type = ACPI_TYPE_INTEGER;
-       params[2].integer.value = func;
-       params[3].type = ACPI_TYPE_BUFFER;
-       params[3].buffer.length = 4;
        /* ACPI is little endian, AABBCCDD becomes {DD,CC,BB,AA} */
        for (i = 0; i < 4; i++)
                args_buff[i] = (arg >> i * 8) & 0xFF;
-       params[3].buffer.pointer = args_buff;
-
-       err = acpi_evaluate_object(handle, "_DSM", &input, &output);
-       if (err) {
-               printk(KERN_INFO "failed to evaluate _DSM: %d\n", err);
-               return err;
-       }
-
-       obj = (union acpi_object *)output.pointer;
 
-       if (obj->type == ACPI_TYPE_INTEGER)
-               if (obj->integer.value == 0x80000002) {
-                       return -ENODEV;
-               }
-
-       if (obj->type == ACPI_TYPE_BUFFER) {
-               if (obj->buffer.length == 4 && result) {
-                       *result = 0;
+       *result = 0;
+       obj = acpi_evaluate_dsm_typed(handle, nouveau_op_dsm_muid, 0x00000100,
+                                     func, &argv4, ACPI_TYPE_BUFFER);
+       if (!obj) {
+               acpi_handle_info(handle, "failed to evaluate _DSM\n");
+               return AE_ERROR;
+       } else {
+               if (obj->buffer.length == 4) {
                        *result |= obj->buffer.pointer[0];
                        *result |= (obj->buffer.pointer[1] << 8);
                        *result |= (obj->buffer.pointer[2] << 16);
                        *result |= (obj->buffer.pointer[3] << 24);
                }
+               ACPI_FREE(obj);
        }
 
-       kfree(output.pointer);
        return 0;
 }
 
-static int nouveau_dsm(acpi_handle handle, int func, int arg, uint32_t *result)
+static int nouveau_dsm(acpi_handle handle, int func, int arg)
 {
-       struct acpi_buffer output = { ACPI_ALLOCATE_BUFFER, NULL };
-       struct acpi_object_list input;
-       union acpi_object params[4];
+       int ret = 0;
        union acpi_object *obj;
-       int err;
-
-       input.count = 4;
-       input.pointer = params;
-       params[0].type = ACPI_TYPE_BUFFER;
-       params[0].buffer.length = sizeof(nouveau_dsm_muid);
-       params[0].buffer.pointer = (char *)nouveau_dsm_muid;
-       params[1].type = ACPI_TYPE_INTEGER;
-       params[1].integer.value = 0x00000102;
-       params[2].type = ACPI_TYPE_INTEGER;
-       params[2].integer.value = func;
-       params[3].type = ACPI_TYPE_INTEGER;
-       params[3].integer.value = arg;
-
-       err = acpi_evaluate_object(handle, "_DSM", &input, &output);
-       if (err) {
-               printk(KERN_INFO "failed to evaluate _DSM: %d\n", err);
-               return err;
-       }
-
-       obj = (union acpi_object *)output.pointer;
-
-       if (obj->type == ACPI_TYPE_INTEGER)
+       union acpi_object argv4 = {
+               .integer.type = ACPI_TYPE_INTEGER,
+               .integer.value = arg,
+       };
+
+       obj = acpi_evaluate_dsm_typed(handle, nouveau_dsm_muid, 0x00000102,
+                                     func, &argv4, ACPI_TYPE_INTEGER);
+       if (!obj) {
+               acpi_handle_info(handle, "failed to evaluate _DSM\n");
+               return AE_ERROR;
+       } else {
                if (obj->integer.value == 0x80000002)
-                       return -ENODEV;
-
-       if (obj->type == ACPI_TYPE_BUFFER) {
-               if (obj->buffer.length == 4 && result) {
-                       *result = 0;
-                       *result |= obj->buffer.pointer[0];
-                       *result |= (obj->buffer.pointer[1] << 8);
-                       *result |= (obj->buffer.pointer[2] << 16);
-                       *result |= (obj->buffer.pointer[3] << 24);
-               }
+                       ret = -ENODEV;
+               ACPI_FREE(obj);
        }
 
-       kfree(output.pointer);
-       return 0;
-}
-
-/* Returns 1 if a DSM function is usable and 0 otherwise */
-static int nouveau_test_dsm(acpi_handle test_handle,
-       int (*dsm_func)(acpi_handle, int, int, uint32_t *),
-       int sfnc)
-{
-       u32 result = 0;
-
-       /* Function 0 returns a Buffer containing available functions. The args
-        * parameter is ignored for function 0, so just put 0 in it */
-       if (dsm_func(test_handle, 0, 0, &result))
-               return 0;
-
-       /* ACPI Spec v4 9.14.1: if bit 0 is zero, no function is supported. If
-        * the n-th bit is enabled, function n is supported */
-       return result & 1 && result & (1 << sfnc);
+       return ret;
 }
 
 static int nouveau_dsm_switch_mux(acpi_handle handle, int mux_id)
 {
        mxm_wmi_call_mxmx(mux_id == NOUVEAU_DSM_LED_STAMINA ? MXM_MXDS_ADAPTER_IGD : MXM_MXDS_ADAPTER_0);
        mxm_wmi_call_mxds(mux_id == NOUVEAU_DSM_LED_STAMINA ? MXM_MXDS_ADAPTER_IGD : MXM_MXDS_ADAPTER_0);
-       return nouveau_dsm(handle, NOUVEAU_DSM_LED, mux_id, NULL);
+       return nouveau_dsm(handle, NOUVEAU_DSM_LED, mux_id);
 }
 
 static int nouveau_dsm_set_discrete_state(acpi_handle handle, enum vga_switcheroo_state state)
@@ -205,7 +143,7 @@ static int nouveau_dsm_set_discrete_state(acpi_handle handle, enum vga_switchero
                arg = NOUVEAU_DSM_POWER_SPEED;
        else
                arg = NOUVEAU_DSM_POWER_STAMINA;
-       nouveau_dsm(handle, NOUVEAU_DSM_POWER, arg, NULL);
+       nouveau_dsm(handle, NOUVEAU_DSM_POWER, arg);
        return 0;
 }
 
@@ -265,11 +203,12 @@ static int nouveau_dsm_pci_probe(struct pci_dev *pdev)
                nouveau_dsm_priv.other_handle = dhandle;
                return false;
        }
-       if (nouveau_test_dsm(dhandle, nouveau_dsm, NOUVEAU_DSM_POWER))
+       if (acpi_check_dsm(dhandle, nouveau_dsm_muid, 0x00000102,
+                          1 << NOUVEAU_DSM_POWER))
                retval |= NOUVEAU_DSM_HAS_MUX;
 
-       if (nouveau_test_dsm(dhandle, nouveau_optimus_dsm,
-               NOUVEAU_DSM_OPTIMUS_CAPS))
+       if (acpi_check_dsm(dhandle, nouveau_op_dsm_muid, 0x00000100,
+                          1 << NOUVEAU_DSM_OPTIMUS_CAPS))
                retval |= NOUVEAU_DSM_HAS_OPT;
 
        if (retval & NOUVEAU_DSM_HAS_OPT) {
@@ -388,6 +327,11 @@ void nouveau_unregister_dsm_handler(void)
        if (nouveau_dsm_priv.optimus_detected || nouveau_dsm_priv.dsm_detected)
                vga_switcheroo_unregister_handler();
 }
+#else
+void nouveau_register_dsm_handler(void) {}
+void nouveau_unregister_dsm_handler(void) {}
+void nouveau_switcheroo_optimus_dsm(void) {}
+#endif
 
 /* retrieve the ROM in 4k blocks */
 static int nouveau_rom_call(acpi_handle rom_handle, uint8_t *bios,