1*d38ceaf9SAlex Deucher /* 2*d38ceaf9SAlex Deucher * Copyright 2012 Advanced Micro Devices, Inc. 3*d38ceaf9SAlex Deucher * 4*d38ceaf9SAlex Deucher * Permission is hereby granted, free of charge, to any person obtaining a 5*d38ceaf9SAlex Deucher * copy of this software and associated documentation files (the "Software"), 6*d38ceaf9SAlex Deucher * to deal in the Software without restriction, including without limitation 7*d38ceaf9SAlex Deucher * the rights to use, copy, modify, merge, publish, distribute, sublicense, 8*d38ceaf9SAlex Deucher * and/or sell copies of the Software, and to permit persons to whom the 9*d38ceaf9SAlex Deucher * Software is furnished to do so, subject to the following conditions: 10*d38ceaf9SAlex Deucher * 11*d38ceaf9SAlex Deucher * The above copyright notice and this permission notice shall be included in 12*d38ceaf9SAlex Deucher * all copies or substantial portions of the Software. 13*d38ceaf9SAlex Deucher * 14*d38ceaf9SAlex Deucher * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 15*d38ceaf9SAlex Deucher * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 16*d38ceaf9SAlex Deucher * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL 17*d38ceaf9SAlex Deucher * THE COPYRIGHT HOLDER(S) OR AUTHOR(S) BE LIABLE FOR ANY CLAIM, DAMAGES OR 18*d38ceaf9SAlex Deucher * OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, 19*d38ceaf9SAlex Deucher * ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR 20*d38ceaf9SAlex Deucher * OTHER DEALINGS IN THE SOFTWARE. 21*d38ceaf9SAlex Deucher * 22*d38ceaf9SAlex Deucher */ 23*d38ceaf9SAlex Deucher 24*d38ceaf9SAlex Deucher #include <linux/pci.h> 25*d38ceaf9SAlex Deucher #include <linux/acpi.h> 26*d38ceaf9SAlex Deucher #include <linux/slab.h> 27*d38ceaf9SAlex Deucher #include <linux/power_supply.h> 28*d38ceaf9SAlex Deucher #include <linux/vga_switcheroo.h> 29*d38ceaf9SAlex Deucher #include <acpi/video.h> 30*d38ceaf9SAlex Deucher #include <drm/drmP.h> 31*d38ceaf9SAlex Deucher #include <drm/drm_crtc_helper.h> 32*d38ceaf9SAlex Deucher #include "amdgpu.h" 33*d38ceaf9SAlex Deucher #include "amdgpu_acpi.h" 34*d38ceaf9SAlex Deucher #include "atom.h" 35*d38ceaf9SAlex Deucher 36*d38ceaf9SAlex Deucher #define ACPI_AC_CLASS "ac_adapter" 37*d38ceaf9SAlex Deucher 38*d38ceaf9SAlex Deucher extern void amdgpu_pm_acpi_event_handler(struct amdgpu_device *adev); 39*d38ceaf9SAlex Deucher 40*d38ceaf9SAlex Deucher struct atif_verify_interface { 41*d38ceaf9SAlex Deucher u16 size; /* structure size in bytes (includes size field) */ 42*d38ceaf9SAlex Deucher u16 version; /* version */ 43*d38ceaf9SAlex Deucher u32 notification_mask; /* supported notifications mask */ 44*d38ceaf9SAlex Deucher u32 function_bits; /* supported functions bit vector */ 45*d38ceaf9SAlex Deucher } __packed; 46*d38ceaf9SAlex Deucher 47*d38ceaf9SAlex Deucher struct atif_system_params { 48*d38ceaf9SAlex Deucher u16 size; /* structure size in bytes (includes size field) */ 49*d38ceaf9SAlex Deucher u32 valid_mask; /* valid flags mask */ 50*d38ceaf9SAlex Deucher u32 flags; /* flags */ 51*d38ceaf9SAlex Deucher u8 command_code; /* notify command code */ 52*d38ceaf9SAlex Deucher } __packed; 53*d38ceaf9SAlex Deucher 54*d38ceaf9SAlex Deucher struct atif_sbios_requests { 55*d38ceaf9SAlex Deucher u16 size; /* structure size in bytes (includes size field) */ 56*d38ceaf9SAlex Deucher u32 pending; /* pending sbios requests */ 57*d38ceaf9SAlex Deucher u8 panel_exp_mode; /* panel expansion mode */ 58*d38ceaf9SAlex Deucher u8 thermal_gfx; /* thermal state: target gfx controller */ 59*d38ceaf9SAlex Deucher u8 thermal_state; /* thermal state: state id (0: exit state, non-0: state) */ 60*d38ceaf9SAlex Deucher u8 forced_power_gfx; /* forced power state: target gfx controller */ 61*d38ceaf9SAlex Deucher u8 forced_power_state; /* forced power state: state id */ 62*d38ceaf9SAlex Deucher u8 system_power_src; /* system power source */ 63*d38ceaf9SAlex Deucher u8 backlight_level; /* panel backlight level (0-255) */ 64*d38ceaf9SAlex Deucher } __packed; 65*d38ceaf9SAlex Deucher 66*d38ceaf9SAlex Deucher #define ATIF_NOTIFY_MASK 0x3 67*d38ceaf9SAlex Deucher #define ATIF_NOTIFY_NONE 0 68*d38ceaf9SAlex Deucher #define ATIF_NOTIFY_81 1 69*d38ceaf9SAlex Deucher #define ATIF_NOTIFY_N 2 70*d38ceaf9SAlex Deucher 71*d38ceaf9SAlex Deucher struct atcs_verify_interface { 72*d38ceaf9SAlex Deucher u16 size; /* structure size in bytes (includes size field) */ 73*d38ceaf9SAlex Deucher u16 version; /* version */ 74*d38ceaf9SAlex Deucher u32 function_bits; /* supported functions bit vector */ 75*d38ceaf9SAlex Deucher } __packed; 76*d38ceaf9SAlex Deucher 77*d38ceaf9SAlex Deucher #define ATCS_VALID_FLAGS_MASK 0x3 78*d38ceaf9SAlex Deucher 79*d38ceaf9SAlex Deucher struct atcs_pref_req_input { 80*d38ceaf9SAlex Deucher u16 size; /* structure size in bytes (includes size field) */ 81*d38ceaf9SAlex Deucher u16 client_id; /* client id (bit 2-0: func num, 7-3: dev num, 15-8: bus num) */ 82*d38ceaf9SAlex Deucher u16 valid_flags_mask; /* valid flags mask */ 83*d38ceaf9SAlex Deucher u16 flags; /* flags */ 84*d38ceaf9SAlex Deucher u8 req_type; /* request type */ 85*d38ceaf9SAlex Deucher u8 perf_req; /* performance request */ 86*d38ceaf9SAlex Deucher } __packed; 87*d38ceaf9SAlex Deucher 88*d38ceaf9SAlex Deucher struct atcs_pref_req_output { 89*d38ceaf9SAlex Deucher u16 size; /* structure size in bytes (includes size field) */ 90*d38ceaf9SAlex Deucher u8 ret_val; /* return value */ 91*d38ceaf9SAlex Deucher } __packed; 92*d38ceaf9SAlex Deucher 93*d38ceaf9SAlex Deucher /* Call the ATIF method 94*d38ceaf9SAlex Deucher */ 95*d38ceaf9SAlex Deucher /** 96*d38ceaf9SAlex Deucher * amdgpu_atif_call - call an ATIF method 97*d38ceaf9SAlex Deucher * 98*d38ceaf9SAlex Deucher * @handle: acpi handle 99*d38ceaf9SAlex Deucher * @function: the ATIF function to execute 100*d38ceaf9SAlex Deucher * @params: ATIF function params 101*d38ceaf9SAlex Deucher * 102*d38ceaf9SAlex Deucher * Executes the requested ATIF function (all asics). 103*d38ceaf9SAlex Deucher * Returns a pointer to the acpi output buffer. 104*d38ceaf9SAlex Deucher */ 105*d38ceaf9SAlex Deucher static union acpi_object *amdgpu_atif_call(acpi_handle handle, int function, 106*d38ceaf9SAlex Deucher struct acpi_buffer *params) 107*d38ceaf9SAlex Deucher { 108*d38ceaf9SAlex Deucher acpi_status status; 109*d38ceaf9SAlex Deucher union acpi_object atif_arg_elements[2]; 110*d38ceaf9SAlex Deucher struct acpi_object_list atif_arg; 111*d38ceaf9SAlex Deucher struct acpi_buffer buffer = { ACPI_ALLOCATE_BUFFER, NULL }; 112*d38ceaf9SAlex Deucher 113*d38ceaf9SAlex Deucher atif_arg.count = 2; 114*d38ceaf9SAlex Deucher atif_arg.pointer = &atif_arg_elements[0]; 115*d38ceaf9SAlex Deucher 116*d38ceaf9SAlex Deucher atif_arg_elements[0].type = ACPI_TYPE_INTEGER; 117*d38ceaf9SAlex Deucher atif_arg_elements[0].integer.value = function; 118*d38ceaf9SAlex Deucher 119*d38ceaf9SAlex Deucher if (params) { 120*d38ceaf9SAlex Deucher atif_arg_elements[1].type = ACPI_TYPE_BUFFER; 121*d38ceaf9SAlex Deucher atif_arg_elements[1].buffer.length = params->length; 122*d38ceaf9SAlex Deucher atif_arg_elements[1].buffer.pointer = params->pointer; 123*d38ceaf9SAlex Deucher } else { 124*d38ceaf9SAlex Deucher /* We need a second fake parameter */ 125*d38ceaf9SAlex Deucher atif_arg_elements[1].type = ACPI_TYPE_INTEGER; 126*d38ceaf9SAlex Deucher atif_arg_elements[1].integer.value = 0; 127*d38ceaf9SAlex Deucher } 128*d38ceaf9SAlex Deucher 129*d38ceaf9SAlex Deucher status = acpi_evaluate_object(handle, "ATIF", &atif_arg, &buffer); 130*d38ceaf9SAlex Deucher 131*d38ceaf9SAlex Deucher /* Fail only if calling the method fails and ATIF is supported */ 132*d38ceaf9SAlex Deucher if (ACPI_FAILURE(status) && status != AE_NOT_FOUND) { 133*d38ceaf9SAlex Deucher DRM_DEBUG_DRIVER("failed to evaluate ATIF got %s\n", 134*d38ceaf9SAlex Deucher acpi_format_exception(status)); 135*d38ceaf9SAlex Deucher kfree(buffer.pointer); 136*d38ceaf9SAlex Deucher return NULL; 137*d38ceaf9SAlex Deucher } 138*d38ceaf9SAlex Deucher 139*d38ceaf9SAlex Deucher return buffer.pointer; 140*d38ceaf9SAlex Deucher } 141*d38ceaf9SAlex Deucher 142*d38ceaf9SAlex Deucher /** 143*d38ceaf9SAlex Deucher * amdgpu_atif_parse_notification - parse supported notifications 144*d38ceaf9SAlex Deucher * 145*d38ceaf9SAlex Deucher * @n: supported notifications struct 146*d38ceaf9SAlex Deucher * @mask: supported notifications mask from ATIF 147*d38ceaf9SAlex Deucher * 148*d38ceaf9SAlex Deucher * Use the supported notifications mask from ATIF function 149*d38ceaf9SAlex Deucher * ATIF_FUNCTION_VERIFY_INTERFACE to determine what notifications 150*d38ceaf9SAlex Deucher * are supported (all asics). 151*d38ceaf9SAlex Deucher */ 152*d38ceaf9SAlex Deucher static void amdgpu_atif_parse_notification(struct amdgpu_atif_notifications *n, u32 mask) 153*d38ceaf9SAlex Deucher { 154*d38ceaf9SAlex Deucher n->display_switch = mask & ATIF_DISPLAY_SWITCH_REQUEST_SUPPORTED; 155*d38ceaf9SAlex Deucher n->expansion_mode_change = mask & ATIF_EXPANSION_MODE_CHANGE_REQUEST_SUPPORTED; 156*d38ceaf9SAlex Deucher n->thermal_state = mask & ATIF_THERMAL_STATE_CHANGE_REQUEST_SUPPORTED; 157*d38ceaf9SAlex Deucher n->forced_power_state = mask & ATIF_FORCED_POWER_STATE_CHANGE_REQUEST_SUPPORTED; 158*d38ceaf9SAlex Deucher n->system_power_state = mask & ATIF_SYSTEM_POWER_SOURCE_CHANGE_REQUEST_SUPPORTED; 159*d38ceaf9SAlex Deucher n->display_conf_change = mask & ATIF_DISPLAY_CONF_CHANGE_REQUEST_SUPPORTED; 160*d38ceaf9SAlex Deucher n->px_gfx_switch = mask & ATIF_PX_GFX_SWITCH_REQUEST_SUPPORTED; 161*d38ceaf9SAlex Deucher n->brightness_change = mask & ATIF_PANEL_BRIGHTNESS_CHANGE_REQUEST_SUPPORTED; 162*d38ceaf9SAlex Deucher n->dgpu_display_event = mask & ATIF_DGPU_DISPLAY_EVENT_SUPPORTED; 163*d38ceaf9SAlex Deucher } 164*d38ceaf9SAlex Deucher 165*d38ceaf9SAlex Deucher /** 166*d38ceaf9SAlex Deucher * amdgpu_atif_parse_functions - parse supported functions 167*d38ceaf9SAlex Deucher * 168*d38ceaf9SAlex Deucher * @f: supported functions struct 169*d38ceaf9SAlex Deucher * @mask: supported functions mask from ATIF 170*d38ceaf9SAlex Deucher * 171*d38ceaf9SAlex Deucher * Use the supported functions mask from ATIF function 172*d38ceaf9SAlex Deucher * ATIF_FUNCTION_VERIFY_INTERFACE to determine what functions 173*d38ceaf9SAlex Deucher * are supported (all asics). 174*d38ceaf9SAlex Deucher */ 175*d38ceaf9SAlex Deucher static void amdgpu_atif_parse_functions(struct amdgpu_atif_functions *f, u32 mask) 176*d38ceaf9SAlex Deucher { 177*d38ceaf9SAlex Deucher f->system_params = mask & ATIF_GET_SYSTEM_PARAMETERS_SUPPORTED; 178*d38ceaf9SAlex Deucher f->sbios_requests = mask & ATIF_GET_SYSTEM_BIOS_REQUESTS_SUPPORTED; 179*d38ceaf9SAlex Deucher f->select_active_disp = mask & ATIF_SELECT_ACTIVE_DISPLAYS_SUPPORTED; 180*d38ceaf9SAlex Deucher f->lid_state = mask & ATIF_GET_LID_STATE_SUPPORTED; 181*d38ceaf9SAlex Deucher f->get_tv_standard = mask & ATIF_GET_TV_STANDARD_FROM_CMOS_SUPPORTED; 182*d38ceaf9SAlex Deucher f->set_tv_standard = mask & ATIF_SET_TV_STANDARD_IN_CMOS_SUPPORTED; 183*d38ceaf9SAlex Deucher f->get_panel_expansion_mode = mask & ATIF_GET_PANEL_EXPANSION_MODE_FROM_CMOS_SUPPORTED; 184*d38ceaf9SAlex Deucher f->set_panel_expansion_mode = mask & ATIF_SET_PANEL_EXPANSION_MODE_IN_CMOS_SUPPORTED; 185*d38ceaf9SAlex Deucher f->temperature_change = mask & ATIF_TEMPERATURE_CHANGE_NOTIFICATION_SUPPORTED; 186*d38ceaf9SAlex Deucher f->graphics_device_types = mask & ATIF_GET_GRAPHICS_DEVICE_TYPES_SUPPORTED; 187*d38ceaf9SAlex Deucher } 188*d38ceaf9SAlex Deucher 189*d38ceaf9SAlex Deucher /** 190*d38ceaf9SAlex Deucher * amdgpu_atif_verify_interface - verify ATIF 191*d38ceaf9SAlex Deucher * 192*d38ceaf9SAlex Deucher * @handle: acpi handle 193*d38ceaf9SAlex Deucher * @atif: amdgpu atif struct 194*d38ceaf9SAlex Deucher * 195*d38ceaf9SAlex Deucher * Execute the ATIF_FUNCTION_VERIFY_INTERFACE ATIF function 196*d38ceaf9SAlex Deucher * to initialize ATIF and determine what features are supported 197*d38ceaf9SAlex Deucher * (all asics). 198*d38ceaf9SAlex Deucher * returns 0 on success, error on failure. 199*d38ceaf9SAlex Deucher */ 200*d38ceaf9SAlex Deucher static int amdgpu_atif_verify_interface(acpi_handle handle, 201*d38ceaf9SAlex Deucher struct amdgpu_atif *atif) 202*d38ceaf9SAlex Deucher { 203*d38ceaf9SAlex Deucher union acpi_object *info; 204*d38ceaf9SAlex Deucher struct atif_verify_interface output; 205*d38ceaf9SAlex Deucher size_t size; 206*d38ceaf9SAlex Deucher int err = 0; 207*d38ceaf9SAlex Deucher 208*d38ceaf9SAlex Deucher info = amdgpu_atif_call(handle, ATIF_FUNCTION_VERIFY_INTERFACE, NULL); 209*d38ceaf9SAlex Deucher if (!info) 210*d38ceaf9SAlex Deucher return -EIO; 211*d38ceaf9SAlex Deucher 212*d38ceaf9SAlex Deucher memset(&output, 0, sizeof(output)); 213*d38ceaf9SAlex Deucher 214*d38ceaf9SAlex Deucher size = *(u16 *) info->buffer.pointer; 215*d38ceaf9SAlex Deucher if (size < 12) { 216*d38ceaf9SAlex Deucher DRM_INFO("ATIF buffer is too small: %zu\n", size); 217*d38ceaf9SAlex Deucher err = -EINVAL; 218*d38ceaf9SAlex Deucher goto out; 219*d38ceaf9SAlex Deucher } 220*d38ceaf9SAlex Deucher size = min(sizeof(output), size); 221*d38ceaf9SAlex Deucher 222*d38ceaf9SAlex Deucher memcpy(&output, info->buffer.pointer, size); 223*d38ceaf9SAlex Deucher 224*d38ceaf9SAlex Deucher /* TODO: check version? */ 225*d38ceaf9SAlex Deucher DRM_DEBUG_DRIVER("ATIF version %u\n", output.version); 226*d38ceaf9SAlex Deucher 227*d38ceaf9SAlex Deucher amdgpu_atif_parse_notification(&atif->notifications, output.notification_mask); 228*d38ceaf9SAlex Deucher amdgpu_atif_parse_functions(&atif->functions, output.function_bits); 229*d38ceaf9SAlex Deucher 230*d38ceaf9SAlex Deucher out: 231*d38ceaf9SAlex Deucher kfree(info); 232*d38ceaf9SAlex Deucher return err; 233*d38ceaf9SAlex Deucher } 234*d38ceaf9SAlex Deucher 235*d38ceaf9SAlex Deucher /** 236*d38ceaf9SAlex Deucher * amdgpu_atif_get_notification_params - determine notify configuration 237*d38ceaf9SAlex Deucher * 238*d38ceaf9SAlex Deucher * @handle: acpi handle 239*d38ceaf9SAlex Deucher * @n: atif notification configuration struct 240*d38ceaf9SAlex Deucher * 241*d38ceaf9SAlex Deucher * Execute the ATIF_FUNCTION_GET_SYSTEM_PARAMETERS ATIF function 242*d38ceaf9SAlex Deucher * to determine if a notifier is used and if so which one 243*d38ceaf9SAlex Deucher * (all asics). This is either Notify(VGA, 0x81) or Notify(VGA, n) 244*d38ceaf9SAlex Deucher * where n is specified in the result if a notifier is used. 245*d38ceaf9SAlex Deucher * Returns 0 on success, error on failure. 246*d38ceaf9SAlex Deucher */ 247*d38ceaf9SAlex Deucher static int amdgpu_atif_get_notification_params(acpi_handle handle, 248*d38ceaf9SAlex Deucher struct amdgpu_atif_notification_cfg *n) 249*d38ceaf9SAlex Deucher { 250*d38ceaf9SAlex Deucher union acpi_object *info; 251*d38ceaf9SAlex Deucher struct atif_system_params params; 252*d38ceaf9SAlex Deucher size_t size; 253*d38ceaf9SAlex Deucher int err = 0; 254*d38ceaf9SAlex Deucher 255*d38ceaf9SAlex Deucher info = amdgpu_atif_call(handle, ATIF_FUNCTION_GET_SYSTEM_PARAMETERS, NULL); 256*d38ceaf9SAlex Deucher if (!info) { 257*d38ceaf9SAlex Deucher err = -EIO; 258*d38ceaf9SAlex Deucher goto out; 259*d38ceaf9SAlex Deucher } 260*d38ceaf9SAlex Deucher 261*d38ceaf9SAlex Deucher size = *(u16 *) info->buffer.pointer; 262*d38ceaf9SAlex Deucher if (size < 10) { 263*d38ceaf9SAlex Deucher err = -EINVAL; 264*d38ceaf9SAlex Deucher goto out; 265*d38ceaf9SAlex Deucher } 266*d38ceaf9SAlex Deucher 267*d38ceaf9SAlex Deucher memset(¶ms, 0, sizeof(params)); 268*d38ceaf9SAlex Deucher size = min(sizeof(params), size); 269*d38ceaf9SAlex Deucher memcpy(¶ms, info->buffer.pointer, size); 270*d38ceaf9SAlex Deucher 271*d38ceaf9SAlex Deucher DRM_DEBUG_DRIVER("SYSTEM_PARAMS: mask = %#x, flags = %#x\n", 272*d38ceaf9SAlex Deucher params.flags, params.valid_mask); 273*d38ceaf9SAlex Deucher params.flags = params.flags & params.valid_mask; 274*d38ceaf9SAlex Deucher 275*d38ceaf9SAlex Deucher if ((params.flags & ATIF_NOTIFY_MASK) == ATIF_NOTIFY_NONE) { 276*d38ceaf9SAlex Deucher n->enabled = false; 277*d38ceaf9SAlex Deucher n->command_code = 0; 278*d38ceaf9SAlex Deucher } else if ((params.flags & ATIF_NOTIFY_MASK) == ATIF_NOTIFY_81) { 279*d38ceaf9SAlex Deucher n->enabled = true; 280*d38ceaf9SAlex Deucher n->command_code = 0x81; 281*d38ceaf9SAlex Deucher } else { 282*d38ceaf9SAlex Deucher if (size < 11) { 283*d38ceaf9SAlex Deucher err = -EINVAL; 284*d38ceaf9SAlex Deucher goto out; 285*d38ceaf9SAlex Deucher } 286*d38ceaf9SAlex Deucher n->enabled = true; 287*d38ceaf9SAlex Deucher n->command_code = params.command_code; 288*d38ceaf9SAlex Deucher } 289*d38ceaf9SAlex Deucher 290*d38ceaf9SAlex Deucher out: 291*d38ceaf9SAlex Deucher DRM_DEBUG_DRIVER("Notification %s, command code = %#x\n", 292*d38ceaf9SAlex Deucher (n->enabled ? "enabled" : "disabled"), 293*d38ceaf9SAlex Deucher n->command_code); 294*d38ceaf9SAlex Deucher kfree(info); 295*d38ceaf9SAlex Deucher return err; 296*d38ceaf9SAlex Deucher } 297*d38ceaf9SAlex Deucher 298*d38ceaf9SAlex Deucher /** 299*d38ceaf9SAlex Deucher * amdgpu_atif_get_sbios_requests - get requested sbios event 300*d38ceaf9SAlex Deucher * 301*d38ceaf9SAlex Deucher * @handle: acpi handle 302*d38ceaf9SAlex Deucher * @req: atif sbios request struct 303*d38ceaf9SAlex Deucher * 304*d38ceaf9SAlex Deucher * Execute the ATIF_FUNCTION_GET_SYSTEM_BIOS_REQUESTS ATIF function 305*d38ceaf9SAlex Deucher * to determine what requests the sbios is making to the driver 306*d38ceaf9SAlex Deucher * (all asics). 307*d38ceaf9SAlex Deucher * Returns 0 on success, error on failure. 308*d38ceaf9SAlex Deucher */ 309*d38ceaf9SAlex Deucher static int amdgpu_atif_get_sbios_requests(acpi_handle handle, 310*d38ceaf9SAlex Deucher struct atif_sbios_requests *req) 311*d38ceaf9SAlex Deucher { 312*d38ceaf9SAlex Deucher union acpi_object *info; 313*d38ceaf9SAlex Deucher size_t size; 314*d38ceaf9SAlex Deucher int count = 0; 315*d38ceaf9SAlex Deucher 316*d38ceaf9SAlex Deucher info = amdgpu_atif_call(handle, ATIF_FUNCTION_GET_SYSTEM_BIOS_REQUESTS, NULL); 317*d38ceaf9SAlex Deucher if (!info) 318*d38ceaf9SAlex Deucher return -EIO; 319*d38ceaf9SAlex Deucher 320*d38ceaf9SAlex Deucher size = *(u16 *)info->buffer.pointer; 321*d38ceaf9SAlex Deucher if (size < 0xd) { 322*d38ceaf9SAlex Deucher count = -EINVAL; 323*d38ceaf9SAlex Deucher goto out; 324*d38ceaf9SAlex Deucher } 325*d38ceaf9SAlex Deucher memset(req, 0, sizeof(*req)); 326*d38ceaf9SAlex Deucher 327*d38ceaf9SAlex Deucher size = min(sizeof(*req), size); 328*d38ceaf9SAlex Deucher memcpy(req, info->buffer.pointer, size); 329*d38ceaf9SAlex Deucher DRM_DEBUG_DRIVER("SBIOS pending requests: %#x\n", req->pending); 330*d38ceaf9SAlex Deucher 331*d38ceaf9SAlex Deucher count = hweight32(req->pending); 332*d38ceaf9SAlex Deucher 333*d38ceaf9SAlex Deucher out: 334*d38ceaf9SAlex Deucher kfree(info); 335*d38ceaf9SAlex Deucher return count; 336*d38ceaf9SAlex Deucher } 337*d38ceaf9SAlex Deucher 338*d38ceaf9SAlex Deucher /** 339*d38ceaf9SAlex Deucher * amdgpu_atif_handler - handle ATIF notify requests 340*d38ceaf9SAlex Deucher * 341*d38ceaf9SAlex Deucher * @adev: amdgpu_device pointer 342*d38ceaf9SAlex Deucher * @event: atif sbios request struct 343*d38ceaf9SAlex Deucher * 344*d38ceaf9SAlex Deucher * Checks the acpi event and if it matches an atif event, 345*d38ceaf9SAlex Deucher * handles it. 346*d38ceaf9SAlex Deucher * Returns NOTIFY code 347*d38ceaf9SAlex Deucher */ 348*d38ceaf9SAlex Deucher int amdgpu_atif_handler(struct amdgpu_device *adev, 349*d38ceaf9SAlex Deucher struct acpi_bus_event *event) 350*d38ceaf9SAlex Deucher { 351*d38ceaf9SAlex Deucher struct amdgpu_atif *atif = &adev->atif; 352*d38ceaf9SAlex Deucher struct atif_sbios_requests req; 353*d38ceaf9SAlex Deucher acpi_handle handle; 354*d38ceaf9SAlex Deucher int count; 355*d38ceaf9SAlex Deucher 356*d38ceaf9SAlex Deucher DRM_DEBUG_DRIVER("event, device_class = %s, type = %#x\n", 357*d38ceaf9SAlex Deucher event->device_class, event->type); 358*d38ceaf9SAlex Deucher 359*d38ceaf9SAlex Deucher if (strcmp(event->device_class, ACPI_VIDEO_CLASS) != 0) 360*d38ceaf9SAlex Deucher return NOTIFY_DONE; 361*d38ceaf9SAlex Deucher 362*d38ceaf9SAlex Deucher if (!atif->notification_cfg.enabled || 363*d38ceaf9SAlex Deucher event->type != atif->notification_cfg.command_code) 364*d38ceaf9SAlex Deucher /* Not our event */ 365*d38ceaf9SAlex Deucher return NOTIFY_DONE; 366*d38ceaf9SAlex Deucher 367*d38ceaf9SAlex Deucher /* Check pending SBIOS requests */ 368*d38ceaf9SAlex Deucher handle = ACPI_HANDLE(&adev->pdev->dev); 369*d38ceaf9SAlex Deucher count = amdgpu_atif_get_sbios_requests(handle, &req); 370*d38ceaf9SAlex Deucher 371*d38ceaf9SAlex Deucher if (count <= 0) 372*d38ceaf9SAlex Deucher return NOTIFY_DONE; 373*d38ceaf9SAlex Deucher 374*d38ceaf9SAlex Deucher DRM_DEBUG_DRIVER("ATIF: %d pending SBIOS requests\n", count); 375*d38ceaf9SAlex Deucher 376*d38ceaf9SAlex Deucher if (req.pending & ATIF_PANEL_BRIGHTNESS_CHANGE_REQUEST) { 377*d38ceaf9SAlex Deucher struct amdgpu_encoder *enc = atif->encoder_for_bl; 378*d38ceaf9SAlex Deucher 379*d38ceaf9SAlex Deucher if (enc) { 380*d38ceaf9SAlex Deucher struct amdgpu_encoder_atom_dig *dig = enc->enc_priv; 381*d38ceaf9SAlex Deucher 382*d38ceaf9SAlex Deucher DRM_DEBUG_DRIVER("Changing brightness to %d\n", 383*d38ceaf9SAlex Deucher req.backlight_level); 384*d38ceaf9SAlex Deucher 385*d38ceaf9SAlex Deucher amdgpu_display_backlight_set_level(adev, enc, req.backlight_level); 386*d38ceaf9SAlex Deucher 387*d38ceaf9SAlex Deucher #if defined(CONFIG_BACKLIGHT_CLASS_DEVICE) || defined(CONFIG_BACKLIGHT_CLASS_DEVICE_MODULE) 388*d38ceaf9SAlex Deucher backlight_force_update(dig->bl_dev, 389*d38ceaf9SAlex Deucher BACKLIGHT_UPDATE_HOTKEY); 390*d38ceaf9SAlex Deucher #endif 391*d38ceaf9SAlex Deucher } 392*d38ceaf9SAlex Deucher } 393*d38ceaf9SAlex Deucher /* TODO: check other events */ 394*d38ceaf9SAlex Deucher 395*d38ceaf9SAlex Deucher /* We've handled the event, stop the notifier chain. The ACPI interface 396*d38ceaf9SAlex Deucher * overloads ACPI_VIDEO_NOTIFY_PROBE, we don't want to send that to 397*d38ceaf9SAlex Deucher * userspace if the event was generated only to signal a SBIOS 398*d38ceaf9SAlex Deucher * request. 399*d38ceaf9SAlex Deucher */ 400*d38ceaf9SAlex Deucher return NOTIFY_BAD; 401*d38ceaf9SAlex Deucher } 402*d38ceaf9SAlex Deucher 403*d38ceaf9SAlex Deucher /* Call the ATCS method 404*d38ceaf9SAlex Deucher */ 405*d38ceaf9SAlex Deucher /** 406*d38ceaf9SAlex Deucher * amdgpu_atcs_call - call an ATCS method 407*d38ceaf9SAlex Deucher * 408*d38ceaf9SAlex Deucher * @handle: acpi handle 409*d38ceaf9SAlex Deucher * @function: the ATCS function to execute 410*d38ceaf9SAlex Deucher * @params: ATCS function params 411*d38ceaf9SAlex Deucher * 412*d38ceaf9SAlex Deucher * Executes the requested ATCS function (all asics). 413*d38ceaf9SAlex Deucher * Returns a pointer to the acpi output buffer. 414*d38ceaf9SAlex Deucher */ 415*d38ceaf9SAlex Deucher static union acpi_object *amdgpu_atcs_call(acpi_handle handle, int function, 416*d38ceaf9SAlex Deucher struct acpi_buffer *params) 417*d38ceaf9SAlex Deucher { 418*d38ceaf9SAlex Deucher acpi_status status; 419*d38ceaf9SAlex Deucher union acpi_object atcs_arg_elements[2]; 420*d38ceaf9SAlex Deucher struct acpi_object_list atcs_arg; 421*d38ceaf9SAlex Deucher struct acpi_buffer buffer = { ACPI_ALLOCATE_BUFFER, NULL }; 422*d38ceaf9SAlex Deucher 423*d38ceaf9SAlex Deucher atcs_arg.count = 2; 424*d38ceaf9SAlex Deucher atcs_arg.pointer = &atcs_arg_elements[0]; 425*d38ceaf9SAlex Deucher 426*d38ceaf9SAlex Deucher atcs_arg_elements[0].type = ACPI_TYPE_INTEGER; 427*d38ceaf9SAlex Deucher atcs_arg_elements[0].integer.value = function; 428*d38ceaf9SAlex Deucher 429*d38ceaf9SAlex Deucher if (params) { 430*d38ceaf9SAlex Deucher atcs_arg_elements[1].type = ACPI_TYPE_BUFFER; 431*d38ceaf9SAlex Deucher atcs_arg_elements[1].buffer.length = params->length; 432*d38ceaf9SAlex Deucher atcs_arg_elements[1].buffer.pointer = params->pointer; 433*d38ceaf9SAlex Deucher } else { 434*d38ceaf9SAlex Deucher /* We need a second fake parameter */ 435*d38ceaf9SAlex Deucher atcs_arg_elements[1].type = ACPI_TYPE_INTEGER; 436*d38ceaf9SAlex Deucher atcs_arg_elements[1].integer.value = 0; 437*d38ceaf9SAlex Deucher } 438*d38ceaf9SAlex Deucher 439*d38ceaf9SAlex Deucher status = acpi_evaluate_object(handle, "ATCS", &atcs_arg, &buffer); 440*d38ceaf9SAlex Deucher 441*d38ceaf9SAlex Deucher /* Fail only if calling the method fails and ATIF is supported */ 442*d38ceaf9SAlex Deucher if (ACPI_FAILURE(status) && status != AE_NOT_FOUND) { 443*d38ceaf9SAlex Deucher DRM_DEBUG_DRIVER("failed to evaluate ATCS got %s\n", 444*d38ceaf9SAlex Deucher acpi_format_exception(status)); 445*d38ceaf9SAlex Deucher kfree(buffer.pointer); 446*d38ceaf9SAlex Deucher return NULL; 447*d38ceaf9SAlex Deucher } 448*d38ceaf9SAlex Deucher 449*d38ceaf9SAlex Deucher return buffer.pointer; 450*d38ceaf9SAlex Deucher } 451*d38ceaf9SAlex Deucher 452*d38ceaf9SAlex Deucher /** 453*d38ceaf9SAlex Deucher * amdgpu_atcs_parse_functions - parse supported functions 454*d38ceaf9SAlex Deucher * 455*d38ceaf9SAlex Deucher * @f: supported functions struct 456*d38ceaf9SAlex Deucher * @mask: supported functions mask from ATCS 457*d38ceaf9SAlex Deucher * 458*d38ceaf9SAlex Deucher * Use the supported functions mask from ATCS function 459*d38ceaf9SAlex Deucher * ATCS_FUNCTION_VERIFY_INTERFACE to determine what functions 460*d38ceaf9SAlex Deucher * are supported (all asics). 461*d38ceaf9SAlex Deucher */ 462*d38ceaf9SAlex Deucher static void amdgpu_atcs_parse_functions(struct amdgpu_atcs_functions *f, u32 mask) 463*d38ceaf9SAlex Deucher { 464*d38ceaf9SAlex Deucher f->get_ext_state = mask & ATCS_GET_EXTERNAL_STATE_SUPPORTED; 465*d38ceaf9SAlex Deucher f->pcie_perf_req = mask & ATCS_PCIE_PERFORMANCE_REQUEST_SUPPORTED; 466*d38ceaf9SAlex Deucher f->pcie_dev_rdy = mask & ATCS_PCIE_DEVICE_READY_NOTIFICATION_SUPPORTED; 467*d38ceaf9SAlex Deucher f->pcie_bus_width = mask & ATCS_SET_PCIE_BUS_WIDTH_SUPPORTED; 468*d38ceaf9SAlex Deucher } 469*d38ceaf9SAlex Deucher 470*d38ceaf9SAlex Deucher /** 471*d38ceaf9SAlex Deucher * amdgpu_atcs_verify_interface - verify ATCS 472*d38ceaf9SAlex Deucher * 473*d38ceaf9SAlex Deucher * @handle: acpi handle 474*d38ceaf9SAlex Deucher * @atcs: amdgpu atcs struct 475*d38ceaf9SAlex Deucher * 476*d38ceaf9SAlex Deucher * Execute the ATCS_FUNCTION_VERIFY_INTERFACE ATCS function 477*d38ceaf9SAlex Deucher * to initialize ATCS and determine what features are supported 478*d38ceaf9SAlex Deucher * (all asics). 479*d38ceaf9SAlex Deucher * returns 0 on success, error on failure. 480*d38ceaf9SAlex Deucher */ 481*d38ceaf9SAlex Deucher static int amdgpu_atcs_verify_interface(acpi_handle handle, 482*d38ceaf9SAlex Deucher struct amdgpu_atcs *atcs) 483*d38ceaf9SAlex Deucher { 484*d38ceaf9SAlex Deucher union acpi_object *info; 485*d38ceaf9SAlex Deucher struct atcs_verify_interface output; 486*d38ceaf9SAlex Deucher size_t size; 487*d38ceaf9SAlex Deucher int err = 0; 488*d38ceaf9SAlex Deucher 489*d38ceaf9SAlex Deucher info = amdgpu_atcs_call(handle, ATCS_FUNCTION_VERIFY_INTERFACE, NULL); 490*d38ceaf9SAlex Deucher if (!info) 491*d38ceaf9SAlex Deucher return -EIO; 492*d38ceaf9SAlex Deucher 493*d38ceaf9SAlex Deucher memset(&output, 0, sizeof(output)); 494*d38ceaf9SAlex Deucher 495*d38ceaf9SAlex Deucher size = *(u16 *) info->buffer.pointer; 496*d38ceaf9SAlex Deucher if (size < 8) { 497*d38ceaf9SAlex Deucher DRM_INFO("ATCS buffer is too small: %zu\n", size); 498*d38ceaf9SAlex Deucher err = -EINVAL; 499*d38ceaf9SAlex Deucher goto out; 500*d38ceaf9SAlex Deucher } 501*d38ceaf9SAlex Deucher size = min(sizeof(output), size); 502*d38ceaf9SAlex Deucher 503*d38ceaf9SAlex Deucher memcpy(&output, info->buffer.pointer, size); 504*d38ceaf9SAlex Deucher 505*d38ceaf9SAlex Deucher /* TODO: check version? */ 506*d38ceaf9SAlex Deucher DRM_DEBUG_DRIVER("ATCS version %u\n", output.version); 507*d38ceaf9SAlex Deucher 508*d38ceaf9SAlex Deucher amdgpu_atcs_parse_functions(&atcs->functions, output.function_bits); 509*d38ceaf9SAlex Deucher 510*d38ceaf9SAlex Deucher out: 511*d38ceaf9SAlex Deucher kfree(info); 512*d38ceaf9SAlex Deucher return err; 513*d38ceaf9SAlex Deucher } 514*d38ceaf9SAlex Deucher 515*d38ceaf9SAlex Deucher /** 516*d38ceaf9SAlex Deucher * amdgpu_acpi_is_pcie_performance_request_supported 517*d38ceaf9SAlex Deucher * 518*d38ceaf9SAlex Deucher * @adev: amdgpu_device pointer 519*d38ceaf9SAlex Deucher * 520*d38ceaf9SAlex Deucher * Check if the ATCS pcie_perf_req and pcie_dev_rdy methods 521*d38ceaf9SAlex Deucher * are supported (all asics). 522*d38ceaf9SAlex Deucher * returns true if supported, false if not. 523*d38ceaf9SAlex Deucher */ 524*d38ceaf9SAlex Deucher bool amdgpu_acpi_is_pcie_performance_request_supported(struct amdgpu_device *adev) 525*d38ceaf9SAlex Deucher { 526*d38ceaf9SAlex Deucher struct amdgpu_atcs *atcs = &adev->atcs; 527*d38ceaf9SAlex Deucher 528*d38ceaf9SAlex Deucher if (atcs->functions.pcie_perf_req && atcs->functions.pcie_dev_rdy) 529*d38ceaf9SAlex Deucher return true; 530*d38ceaf9SAlex Deucher 531*d38ceaf9SAlex Deucher return false; 532*d38ceaf9SAlex Deucher } 533*d38ceaf9SAlex Deucher 534*d38ceaf9SAlex Deucher /** 535*d38ceaf9SAlex Deucher * amdgpu_acpi_pcie_notify_device_ready 536*d38ceaf9SAlex Deucher * 537*d38ceaf9SAlex Deucher * @adev: amdgpu_device pointer 538*d38ceaf9SAlex Deucher * 539*d38ceaf9SAlex Deucher * Executes the PCIE_DEVICE_READY_NOTIFICATION method 540*d38ceaf9SAlex Deucher * (all asics). 541*d38ceaf9SAlex Deucher * returns 0 on success, error on failure. 542*d38ceaf9SAlex Deucher */ 543*d38ceaf9SAlex Deucher int amdgpu_acpi_pcie_notify_device_ready(struct amdgpu_device *adev) 544*d38ceaf9SAlex Deucher { 545*d38ceaf9SAlex Deucher acpi_handle handle; 546*d38ceaf9SAlex Deucher union acpi_object *info; 547*d38ceaf9SAlex Deucher struct amdgpu_atcs *atcs = &adev->atcs; 548*d38ceaf9SAlex Deucher 549*d38ceaf9SAlex Deucher /* Get the device handle */ 550*d38ceaf9SAlex Deucher handle = ACPI_HANDLE(&adev->pdev->dev); 551*d38ceaf9SAlex Deucher if (!handle) 552*d38ceaf9SAlex Deucher return -EINVAL; 553*d38ceaf9SAlex Deucher 554*d38ceaf9SAlex Deucher if (!atcs->functions.pcie_dev_rdy) 555*d38ceaf9SAlex Deucher return -EINVAL; 556*d38ceaf9SAlex Deucher 557*d38ceaf9SAlex Deucher info = amdgpu_atcs_call(handle, ATCS_FUNCTION_PCIE_DEVICE_READY_NOTIFICATION, NULL); 558*d38ceaf9SAlex Deucher if (!info) 559*d38ceaf9SAlex Deucher return -EIO; 560*d38ceaf9SAlex Deucher 561*d38ceaf9SAlex Deucher kfree(info); 562*d38ceaf9SAlex Deucher 563*d38ceaf9SAlex Deucher return 0; 564*d38ceaf9SAlex Deucher } 565*d38ceaf9SAlex Deucher 566*d38ceaf9SAlex Deucher /** 567*d38ceaf9SAlex Deucher * amdgpu_acpi_pcie_performance_request 568*d38ceaf9SAlex Deucher * 569*d38ceaf9SAlex Deucher * @adev: amdgpu_device pointer 570*d38ceaf9SAlex Deucher * @perf_req: requested perf level (pcie gen speed) 571*d38ceaf9SAlex Deucher * @advertise: set advertise caps flag if set 572*d38ceaf9SAlex Deucher * 573*d38ceaf9SAlex Deucher * Executes the PCIE_PERFORMANCE_REQUEST method to 574*d38ceaf9SAlex Deucher * change the pcie gen speed (all asics). 575*d38ceaf9SAlex Deucher * returns 0 on success, error on failure. 576*d38ceaf9SAlex Deucher */ 577*d38ceaf9SAlex Deucher int amdgpu_acpi_pcie_performance_request(struct amdgpu_device *adev, 578*d38ceaf9SAlex Deucher u8 perf_req, bool advertise) 579*d38ceaf9SAlex Deucher { 580*d38ceaf9SAlex Deucher acpi_handle handle; 581*d38ceaf9SAlex Deucher union acpi_object *info; 582*d38ceaf9SAlex Deucher struct amdgpu_atcs *atcs = &adev->atcs; 583*d38ceaf9SAlex Deucher struct atcs_pref_req_input atcs_input; 584*d38ceaf9SAlex Deucher struct atcs_pref_req_output atcs_output; 585*d38ceaf9SAlex Deucher struct acpi_buffer params; 586*d38ceaf9SAlex Deucher size_t size; 587*d38ceaf9SAlex Deucher u32 retry = 3; 588*d38ceaf9SAlex Deucher 589*d38ceaf9SAlex Deucher /* Get the device handle */ 590*d38ceaf9SAlex Deucher handle = ACPI_HANDLE(&adev->pdev->dev); 591*d38ceaf9SAlex Deucher if (!handle) 592*d38ceaf9SAlex Deucher return -EINVAL; 593*d38ceaf9SAlex Deucher 594*d38ceaf9SAlex Deucher if (!atcs->functions.pcie_perf_req) 595*d38ceaf9SAlex Deucher return -EINVAL; 596*d38ceaf9SAlex Deucher 597*d38ceaf9SAlex Deucher atcs_input.size = sizeof(struct atcs_pref_req_input); 598*d38ceaf9SAlex Deucher /* client id (bit 2-0: func num, 7-3: dev num, 15-8: bus num) */ 599*d38ceaf9SAlex Deucher atcs_input.client_id = adev->pdev->devfn | (adev->pdev->bus->number << 8); 600*d38ceaf9SAlex Deucher atcs_input.valid_flags_mask = ATCS_VALID_FLAGS_MASK; 601*d38ceaf9SAlex Deucher atcs_input.flags = ATCS_WAIT_FOR_COMPLETION; 602*d38ceaf9SAlex Deucher if (advertise) 603*d38ceaf9SAlex Deucher atcs_input.flags |= ATCS_ADVERTISE_CAPS; 604*d38ceaf9SAlex Deucher atcs_input.req_type = ATCS_PCIE_LINK_SPEED; 605*d38ceaf9SAlex Deucher atcs_input.perf_req = perf_req; 606*d38ceaf9SAlex Deucher 607*d38ceaf9SAlex Deucher params.length = sizeof(struct atcs_pref_req_input); 608*d38ceaf9SAlex Deucher params.pointer = &atcs_input; 609*d38ceaf9SAlex Deucher 610*d38ceaf9SAlex Deucher while (retry--) { 611*d38ceaf9SAlex Deucher info = amdgpu_atcs_call(handle, ATCS_FUNCTION_PCIE_PERFORMANCE_REQUEST, ¶ms); 612*d38ceaf9SAlex Deucher if (!info) 613*d38ceaf9SAlex Deucher return -EIO; 614*d38ceaf9SAlex Deucher 615*d38ceaf9SAlex Deucher memset(&atcs_output, 0, sizeof(atcs_output)); 616*d38ceaf9SAlex Deucher 617*d38ceaf9SAlex Deucher size = *(u16 *) info->buffer.pointer; 618*d38ceaf9SAlex Deucher if (size < 3) { 619*d38ceaf9SAlex Deucher DRM_INFO("ATCS buffer is too small: %zu\n", size); 620*d38ceaf9SAlex Deucher kfree(info); 621*d38ceaf9SAlex Deucher return -EINVAL; 622*d38ceaf9SAlex Deucher } 623*d38ceaf9SAlex Deucher size = min(sizeof(atcs_output), size); 624*d38ceaf9SAlex Deucher 625*d38ceaf9SAlex Deucher memcpy(&atcs_output, info->buffer.pointer, size); 626*d38ceaf9SAlex Deucher 627*d38ceaf9SAlex Deucher kfree(info); 628*d38ceaf9SAlex Deucher 629*d38ceaf9SAlex Deucher switch (atcs_output.ret_val) { 630*d38ceaf9SAlex Deucher case ATCS_REQUEST_REFUSED: 631*d38ceaf9SAlex Deucher default: 632*d38ceaf9SAlex Deucher return -EINVAL; 633*d38ceaf9SAlex Deucher case ATCS_REQUEST_COMPLETE: 634*d38ceaf9SAlex Deucher return 0; 635*d38ceaf9SAlex Deucher case ATCS_REQUEST_IN_PROGRESS: 636*d38ceaf9SAlex Deucher udelay(10); 637*d38ceaf9SAlex Deucher break; 638*d38ceaf9SAlex Deucher } 639*d38ceaf9SAlex Deucher } 640*d38ceaf9SAlex Deucher 641*d38ceaf9SAlex Deucher return 0; 642*d38ceaf9SAlex Deucher } 643*d38ceaf9SAlex Deucher 644*d38ceaf9SAlex Deucher /** 645*d38ceaf9SAlex Deucher * amdgpu_acpi_event - handle notify events 646*d38ceaf9SAlex Deucher * 647*d38ceaf9SAlex Deucher * @nb: notifier block 648*d38ceaf9SAlex Deucher * @val: val 649*d38ceaf9SAlex Deucher * @data: acpi event 650*d38ceaf9SAlex Deucher * 651*d38ceaf9SAlex Deucher * Calls relevant amdgpu functions in response to various 652*d38ceaf9SAlex Deucher * acpi events. 653*d38ceaf9SAlex Deucher * Returns NOTIFY code 654*d38ceaf9SAlex Deucher */ 655*d38ceaf9SAlex Deucher static int amdgpu_acpi_event(struct notifier_block *nb, 656*d38ceaf9SAlex Deucher unsigned long val, 657*d38ceaf9SAlex Deucher void *data) 658*d38ceaf9SAlex Deucher { 659*d38ceaf9SAlex Deucher struct amdgpu_device *adev = container_of(nb, struct amdgpu_device, acpi_nb); 660*d38ceaf9SAlex Deucher struct acpi_bus_event *entry = (struct acpi_bus_event *)data; 661*d38ceaf9SAlex Deucher 662*d38ceaf9SAlex Deucher if (strcmp(entry->device_class, ACPI_AC_CLASS) == 0) { 663*d38ceaf9SAlex Deucher if (power_supply_is_system_supplied() > 0) 664*d38ceaf9SAlex Deucher DRM_DEBUG_DRIVER("pm: AC\n"); 665*d38ceaf9SAlex Deucher else 666*d38ceaf9SAlex Deucher DRM_DEBUG_DRIVER("pm: DC\n"); 667*d38ceaf9SAlex Deucher 668*d38ceaf9SAlex Deucher amdgpu_pm_acpi_event_handler(adev); 669*d38ceaf9SAlex Deucher } 670*d38ceaf9SAlex Deucher 671*d38ceaf9SAlex Deucher /* Check for pending SBIOS requests */ 672*d38ceaf9SAlex Deucher return amdgpu_atif_handler(adev, entry); 673*d38ceaf9SAlex Deucher } 674*d38ceaf9SAlex Deucher 675*d38ceaf9SAlex Deucher /* Call all ACPI methods here */ 676*d38ceaf9SAlex Deucher /** 677*d38ceaf9SAlex Deucher * amdgpu_acpi_init - init driver acpi support 678*d38ceaf9SAlex Deucher * 679*d38ceaf9SAlex Deucher * @adev: amdgpu_device pointer 680*d38ceaf9SAlex Deucher * 681*d38ceaf9SAlex Deucher * Verifies the AMD ACPI interfaces and registers with the acpi 682*d38ceaf9SAlex Deucher * notifier chain (all asics). 683*d38ceaf9SAlex Deucher * Returns 0 on success, error on failure. 684*d38ceaf9SAlex Deucher */ 685*d38ceaf9SAlex Deucher int amdgpu_acpi_init(struct amdgpu_device *adev) 686*d38ceaf9SAlex Deucher { 687*d38ceaf9SAlex Deucher acpi_handle handle; 688*d38ceaf9SAlex Deucher struct amdgpu_atif *atif = &adev->atif; 689*d38ceaf9SAlex Deucher struct amdgpu_atcs *atcs = &adev->atcs; 690*d38ceaf9SAlex Deucher int ret; 691*d38ceaf9SAlex Deucher 692*d38ceaf9SAlex Deucher /* Get the device handle */ 693*d38ceaf9SAlex Deucher handle = ACPI_HANDLE(&adev->pdev->dev); 694*d38ceaf9SAlex Deucher 695*d38ceaf9SAlex Deucher if (!adev->bios || !handle) 696*d38ceaf9SAlex Deucher return 0; 697*d38ceaf9SAlex Deucher 698*d38ceaf9SAlex Deucher /* Call the ATCS method */ 699*d38ceaf9SAlex Deucher ret = amdgpu_atcs_verify_interface(handle, atcs); 700*d38ceaf9SAlex Deucher if (ret) { 701*d38ceaf9SAlex Deucher DRM_DEBUG_DRIVER("Call to ATCS verify_interface failed: %d\n", ret); 702*d38ceaf9SAlex Deucher } 703*d38ceaf9SAlex Deucher 704*d38ceaf9SAlex Deucher /* Call the ATIF method */ 705*d38ceaf9SAlex Deucher ret = amdgpu_atif_verify_interface(handle, atif); 706*d38ceaf9SAlex Deucher if (ret) { 707*d38ceaf9SAlex Deucher DRM_DEBUG_DRIVER("Call to ATIF verify_interface failed: %d\n", ret); 708*d38ceaf9SAlex Deucher goto out; 709*d38ceaf9SAlex Deucher } 710*d38ceaf9SAlex Deucher 711*d38ceaf9SAlex Deucher if (atif->notifications.brightness_change) { 712*d38ceaf9SAlex Deucher struct drm_encoder *tmp; 713*d38ceaf9SAlex Deucher 714*d38ceaf9SAlex Deucher /* Find the encoder controlling the brightness */ 715*d38ceaf9SAlex Deucher list_for_each_entry(tmp, &adev->ddev->mode_config.encoder_list, 716*d38ceaf9SAlex Deucher head) { 717*d38ceaf9SAlex Deucher struct amdgpu_encoder *enc = to_amdgpu_encoder(tmp); 718*d38ceaf9SAlex Deucher 719*d38ceaf9SAlex Deucher if ((enc->devices & (ATOM_DEVICE_LCD_SUPPORT)) && 720*d38ceaf9SAlex Deucher enc->enc_priv) { 721*d38ceaf9SAlex Deucher if (adev->is_atom_bios) { 722*d38ceaf9SAlex Deucher struct amdgpu_encoder_atom_dig *dig = enc->enc_priv; 723*d38ceaf9SAlex Deucher if (dig->bl_dev) { 724*d38ceaf9SAlex Deucher atif->encoder_for_bl = enc; 725*d38ceaf9SAlex Deucher break; 726*d38ceaf9SAlex Deucher } 727*d38ceaf9SAlex Deucher } 728*d38ceaf9SAlex Deucher } 729*d38ceaf9SAlex Deucher } 730*d38ceaf9SAlex Deucher } 731*d38ceaf9SAlex Deucher 732*d38ceaf9SAlex Deucher if (atif->functions.sbios_requests && !atif->functions.system_params) { 733*d38ceaf9SAlex Deucher /* XXX check this workraround, if sbios request function is 734*d38ceaf9SAlex Deucher * present we have to see how it's configured in the system 735*d38ceaf9SAlex Deucher * params 736*d38ceaf9SAlex Deucher */ 737*d38ceaf9SAlex Deucher atif->functions.system_params = true; 738*d38ceaf9SAlex Deucher } 739*d38ceaf9SAlex Deucher 740*d38ceaf9SAlex Deucher if (atif->functions.system_params) { 741*d38ceaf9SAlex Deucher ret = amdgpu_atif_get_notification_params(handle, 742*d38ceaf9SAlex Deucher &atif->notification_cfg); 743*d38ceaf9SAlex Deucher if (ret) { 744*d38ceaf9SAlex Deucher DRM_DEBUG_DRIVER("Call to GET_SYSTEM_PARAMS failed: %d\n", 745*d38ceaf9SAlex Deucher ret); 746*d38ceaf9SAlex Deucher /* Disable notification */ 747*d38ceaf9SAlex Deucher atif->notification_cfg.enabled = false; 748*d38ceaf9SAlex Deucher } 749*d38ceaf9SAlex Deucher } 750*d38ceaf9SAlex Deucher 751*d38ceaf9SAlex Deucher out: 752*d38ceaf9SAlex Deucher adev->acpi_nb.notifier_call = amdgpu_acpi_event; 753*d38ceaf9SAlex Deucher register_acpi_notifier(&adev->acpi_nb); 754*d38ceaf9SAlex Deucher 755*d38ceaf9SAlex Deucher return ret; 756*d38ceaf9SAlex Deucher } 757*d38ceaf9SAlex Deucher 758*d38ceaf9SAlex Deucher /** 759*d38ceaf9SAlex Deucher * amdgpu_acpi_fini - tear down driver acpi support 760*d38ceaf9SAlex Deucher * 761*d38ceaf9SAlex Deucher * @adev: amdgpu_device pointer 762*d38ceaf9SAlex Deucher * 763*d38ceaf9SAlex Deucher * Unregisters with the acpi notifier chain (all asics). 764*d38ceaf9SAlex Deucher */ 765*d38ceaf9SAlex Deucher void amdgpu_acpi_fini(struct amdgpu_device *adev) 766*d38ceaf9SAlex Deucher { 767*d38ceaf9SAlex Deucher unregister_acpi_notifier(&adev->acpi_nb); 768*d38ceaf9SAlex Deucher } 769