diff options
Diffstat (limited to 'drivers/gpu/drm/nouveau/nouveau_acpi.c')
-rw-r--r-- | drivers/gpu/drm/nouveau/nouveau_acpi.c | 138 |
1 files changed, 38 insertions, 100 deletions
diff --git a/drivers/gpu/drm/nouveau/nouveau_acpi.c b/drivers/gpu/drm/nouveau/nouveau_acpi.c index ba0183fb84f3..3c149617cfcb 100644 --- a/drivers/gpu/drm/nouveau/nouveau_acpi.c +++ b/drivers/gpu/drm/nouveau/nouveau_acpi.c @@ -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" @@ -78,124 +73,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 +142,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 +202,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) { |