1254885Sdumbbell/* 2254885Sdumbbell * Copyright 2012 Advanced Micro Devices, Inc. 3254885Sdumbbell * 4254885Sdumbbell * Permission is hereby granted, free of charge, to any person obtaining a 5254885Sdumbbell * copy of this software and associated documentation files (the "Software"), 6254885Sdumbbell * to deal in the Software without restriction, including without limitation 7254885Sdumbbell * the rights to use, copy, modify, merge, publish, distribute, sublicense, 8254885Sdumbbell * and/or sell copies of the Software, and to permit persons to whom the 9254885Sdumbbell * Software is furnished to do so, subject to the following conditions: 10254885Sdumbbell * 11254885Sdumbbell * The above copyright notice and this permission notice shall be included in 12254885Sdumbbell * all copies or substantial portions of the Software. 13254885Sdumbbell * 14254885Sdumbbell * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 15254885Sdumbbell * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 16254885Sdumbbell * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL 17254885Sdumbbell * THE COPYRIGHT HOLDER(S) OR AUTHOR(S) BE LIABLE FOR ANY CLAIM, DAMAGES OR 18254885Sdumbbell * OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, 19254885Sdumbbell * ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR 20254885Sdumbbell * OTHER DEALINGS IN THE SOFTWARE. 21254885Sdumbbell * 22254885Sdumbbell */ 23254885Sdumbbell 24254885Sdumbbell#include <sys/cdefs.h> 25254885Sdumbbell__FBSDID("$FreeBSD$"); 26254885Sdumbbell 27254885Sdumbbell#include <dev/drm2/drmP.h> 28254885Sdumbbell#include <dev/drm2/drm_crtc_helper.h> 29254885Sdumbbell#include "radeon.h" 30254885Sdumbbell#include "radeon_acpi.h" 31254885Sdumbbell#include "atom.h" 32254885Sdumbbell 33254885Sdumbbell#define ACPI_AC_CLASS "ac_adapter" 34254885Sdumbbell 35254885Sdumbbellstruct atif_verify_interface { 36254885Sdumbbell u16 size; /* structure size in bytes (includes size field) */ 37254885Sdumbbell u16 version; /* version */ 38254885Sdumbbell u32 notification_mask; /* supported notifications mask */ 39254885Sdumbbell u32 function_bits; /* supported functions bit vector */ 40254885Sdumbbell} __packed; 41254885Sdumbbell 42254885Sdumbbellstruct atif_system_params { 43254885Sdumbbell u16 size; /* structure size in bytes (includes size field) */ 44254885Sdumbbell u32 valid_mask; /* valid flags mask */ 45254885Sdumbbell u32 flags; /* flags */ 46254885Sdumbbell u8 command_code; /* notify command code */ 47254885Sdumbbell} __packed; 48254885Sdumbbell 49254885Sdumbbellstruct atif_sbios_requests { 50254885Sdumbbell u16 size; /* structure size in bytes (includes size field) */ 51254885Sdumbbell u32 pending; /* pending sbios requests */ 52254885Sdumbbell u8 panel_exp_mode; /* panel expansion mode */ 53254885Sdumbbell u8 thermal_gfx; /* thermal state: target gfx controller */ 54254885Sdumbbell u8 thermal_state; /* thermal state: state id (0: exit state, non-0: state) */ 55254885Sdumbbell u8 forced_power_gfx; /* forced power state: target gfx controller */ 56254885Sdumbbell u8 forced_power_state; /* forced power state: state id */ 57254885Sdumbbell u8 system_power_src; /* system power source */ 58254885Sdumbbell u8 backlight_level; /* panel backlight level (0-255) */ 59254885Sdumbbell} __packed; 60254885Sdumbbell 61254885Sdumbbell#define ATIF_NOTIFY_MASK 0x3 62254885Sdumbbell#define ATIF_NOTIFY_NONE 0 63254885Sdumbbell#define ATIF_NOTIFY_81 1 64254885Sdumbbell#define ATIF_NOTIFY_N 2 65254885Sdumbbell 66254885Sdumbbellstruct atcs_verify_interface { 67254885Sdumbbell u16 size; /* structure size in bytes (includes size field) */ 68254885Sdumbbell u16 version; /* version */ 69254885Sdumbbell u32 function_bits; /* supported functions bit vector */ 70254885Sdumbbell} __packed; 71254885Sdumbbell 72254885Sdumbbell/* Call the ATIF method 73254885Sdumbbell */ 74254885Sdumbbell/** 75254885Sdumbbell * radeon_atif_call - call an ATIF method 76254885Sdumbbell * 77254885Sdumbbell * @handle: acpi handle 78254885Sdumbbell * @function: the ATIF function to execute 79254885Sdumbbell * @params: ATIF function params 80254885Sdumbbell * 81254885Sdumbbell * Executes the requested ATIF function (all asics). 82254885Sdumbbell * Returns a pointer to the acpi output buffer. 83254885Sdumbbell */ 84254885Sdumbbellstatic ACPI_OBJECT *radeon_atif_call(ACPI_HANDLE handle, int function, 85254885Sdumbbell ACPI_BUFFER *params) 86254885Sdumbbell{ 87254885Sdumbbell ACPI_STATUS status; 88254885Sdumbbell ACPI_OBJECT atif_arg_elements[2]; 89254885Sdumbbell ACPI_OBJECT_LIST atif_arg; 90254885Sdumbbell ACPI_BUFFER buffer = { ACPI_ALLOCATE_BUFFER, NULL }; 91254885Sdumbbell 92254885Sdumbbell atif_arg.Count = 2; 93254885Sdumbbell atif_arg.Pointer = &atif_arg_elements[0]; 94254885Sdumbbell 95254885Sdumbbell atif_arg_elements[0].Type = ACPI_TYPE_INTEGER; 96254885Sdumbbell atif_arg_elements[0].Integer.Value = function; 97254885Sdumbbell 98254885Sdumbbell if (params) { 99254885Sdumbbell atif_arg_elements[1].Type = ACPI_TYPE_BUFFER; 100254885Sdumbbell atif_arg_elements[1].Buffer.Length = params->Length; 101254885Sdumbbell atif_arg_elements[1].Buffer.Pointer = params->Pointer; 102254885Sdumbbell } else { 103254885Sdumbbell /* We need a second fake parameter */ 104254885Sdumbbell atif_arg_elements[1].Type = ACPI_TYPE_INTEGER; 105254885Sdumbbell atif_arg_elements[1].Integer.Value = 0; 106254885Sdumbbell } 107254885Sdumbbell 108254885Sdumbbell status = AcpiEvaluateObject(handle, "ATIF", &atif_arg, &buffer); 109254885Sdumbbell 110254885Sdumbbell /* Fail only if calling the method fails and ATIF is supported */ 111254885Sdumbbell if (ACPI_FAILURE(status) && status != AE_NOT_FOUND) { 112254885Sdumbbell DRM_DEBUG_DRIVER("failed to evaluate ATIF got %s\n", 113254885Sdumbbell AcpiFormatException(status)); 114254885Sdumbbell AcpiOsFree(buffer.Pointer); 115254885Sdumbbell return NULL; 116254885Sdumbbell } 117254885Sdumbbell 118254885Sdumbbell return buffer.Pointer; 119254885Sdumbbell} 120254885Sdumbbell 121254885Sdumbbell/** 122254885Sdumbbell * radeon_atif_parse_notification - parse supported notifications 123254885Sdumbbell * 124254885Sdumbbell * @n: supported notifications struct 125254885Sdumbbell * @mask: supported notifications mask from ATIF 126254885Sdumbbell * 127254885Sdumbbell * Use the supported notifications mask from ATIF function 128254885Sdumbbell * ATIF_FUNCTION_VERIFY_INTERFACE to determine what notifications 129254885Sdumbbell * are supported (all asics). 130254885Sdumbbell */ 131254885Sdumbbellstatic void radeon_atif_parse_notification(struct radeon_atif_notifications *n, u32 mask) 132254885Sdumbbell{ 133254885Sdumbbell n->display_switch = mask & ATIF_DISPLAY_SWITCH_REQUEST_SUPPORTED; 134254885Sdumbbell n->expansion_mode_change = mask & ATIF_EXPANSION_MODE_CHANGE_REQUEST_SUPPORTED; 135254885Sdumbbell n->thermal_state = mask & ATIF_THERMAL_STATE_CHANGE_REQUEST_SUPPORTED; 136254885Sdumbbell n->forced_power_state = mask & ATIF_FORCED_POWER_STATE_CHANGE_REQUEST_SUPPORTED; 137254885Sdumbbell n->system_power_state = mask & ATIF_SYSTEM_POWER_SOURCE_CHANGE_REQUEST_SUPPORTED; 138254885Sdumbbell n->display_conf_change = mask & ATIF_DISPLAY_CONF_CHANGE_REQUEST_SUPPORTED; 139254885Sdumbbell n->px_gfx_switch = mask & ATIF_PX_GFX_SWITCH_REQUEST_SUPPORTED; 140254885Sdumbbell n->brightness_change = mask & ATIF_PANEL_BRIGHTNESS_CHANGE_REQUEST_SUPPORTED; 141254885Sdumbbell n->dgpu_display_event = mask & ATIF_DGPU_DISPLAY_EVENT_SUPPORTED; 142254885Sdumbbell} 143254885Sdumbbell 144254885Sdumbbell/** 145254885Sdumbbell * radeon_atif_parse_functions - parse supported functions 146254885Sdumbbell * 147254885Sdumbbell * @f: supported functions struct 148254885Sdumbbell * @mask: supported functions mask from ATIF 149254885Sdumbbell * 150254885Sdumbbell * Use the supported functions mask from ATIF function 151254885Sdumbbell * ATIF_FUNCTION_VERIFY_INTERFACE to determine what functions 152254885Sdumbbell * are supported (all asics). 153254885Sdumbbell */ 154254885Sdumbbellstatic void radeon_atif_parse_functions(struct radeon_atif_functions *f, u32 mask) 155254885Sdumbbell{ 156254885Sdumbbell f->system_params = mask & ATIF_GET_SYSTEM_PARAMETERS_SUPPORTED; 157254885Sdumbbell f->sbios_requests = mask & ATIF_GET_SYSTEM_BIOS_REQUESTS_SUPPORTED; 158254885Sdumbbell f->select_active_disp = mask & ATIF_SELECT_ACTIVE_DISPLAYS_SUPPORTED; 159254885Sdumbbell f->lid_state = mask & ATIF_GET_LID_STATE_SUPPORTED; 160254885Sdumbbell f->get_tv_standard = mask & ATIF_GET_TV_STANDARD_FROM_CMOS_SUPPORTED; 161254885Sdumbbell f->set_tv_standard = mask & ATIF_SET_TV_STANDARD_IN_CMOS_SUPPORTED; 162254885Sdumbbell f->get_panel_expansion_mode = mask & ATIF_GET_PANEL_EXPANSION_MODE_FROM_CMOS_SUPPORTED; 163254885Sdumbbell f->set_panel_expansion_mode = mask & ATIF_SET_PANEL_EXPANSION_MODE_IN_CMOS_SUPPORTED; 164254885Sdumbbell f->temperature_change = mask & ATIF_TEMPERATURE_CHANGE_NOTIFICATION_SUPPORTED; 165254885Sdumbbell f->graphics_device_types = mask & ATIF_GET_GRAPHICS_DEVICE_TYPES_SUPPORTED; 166254885Sdumbbell} 167254885Sdumbbell 168254885Sdumbbell/** 169254885Sdumbbell * radeon_atif_verify_interface - verify ATIF 170254885Sdumbbell * 171254885Sdumbbell * @handle: acpi handle 172254885Sdumbbell * @atif: radeon atif struct 173254885Sdumbbell * 174254885Sdumbbell * Execute the ATIF_FUNCTION_VERIFY_INTERFACE ATIF function 175254885Sdumbbell * to initialize ATIF and determine what features are supported 176254885Sdumbbell * (all asics). 177254885Sdumbbell * returns 0 on success, error on failure. 178254885Sdumbbell */ 179254885Sdumbbellstatic int radeon_atif_verify_interface(ACPI_HANDLE handle, 180254885Sdumbbell struct radeon_atif *atif) 181254885Sdumbbell{ 182254885Sdumbbell ACPI_OBJECT *info; 183254885Sdumbbell struct atif_verify_interface output; 184254885Sdumbbell size_t size; 185254885Sdumbbell int err = 0; 186254885Sdumbbell 187254885Sdumbbell info = radeon_atif_call(handle, ATIF_FUNCTION_VERIFY_INTERFACE, NULL); 188254885Sdumbbell if (!info) 189254885Sdumbbell return -EIO; 190254885Sdumbbell 191254885Sdumbbell memset(&output, 0, sizeof(output)); 192254885Sdumbbell 193254885Sdumbbell size = *(u16 *) info->Buffer.Pointer; 194254885Sdumbbell if (size < 12) { 195254885Sdumbbell DRM_INFO("ATIF buffer is too small: %zu\n", size); 196254885Sdumbbell err = -EINVAL; 197254885Sdumbbell goto out; 198254885Sdumbbell } 199254885Sdumbbell size = min(sizeof(output), size); 200254885Sdumbbell 201254885Sdumbbell memcpy(&output, info->Buffer.Pointer, size); 202254885Sdumbbell 203254885Sdumbbell /* TODO: check version? */ 204254885Sdumbbell DRM_DEBUG_DRIVER("ATIF version %u\n", output.version); 205254885Sdumbbell 206254885Sdumbbell radeon_atif_parse_notification(&atif->notifications, output.notification_mask); 207254885Sdumbbell radeon_atif_parse_functions(&atif->functions, output.function_bits); 208254885Sdumbbell 209254885Sdumbbellout: 210254885Sdumbbell AcpiOsFree(info); 211254885Sdumbbell return err; 212254885Sdumbbell} 213254885Sdumbbell 214254885Sdumbbell/** 215254885Sdumbbell * radeon_atif_get_notification_params - determine notify configuration 216254885Sdumbbell * 217254885Sdumbbell * @handle: acpi handle 218254885Sdumbbell * @n: atif notification configuration struct 219254885Sdumbbell * 220254885Sdumbbell * Execute the ATIF_FUNCTION_GET_SYSTEM_PARAMETERS ATIF function 221254885Sdumbbell * to determine if a notifier is used and if so which one 222254885Sdumbbell * (all asics). This is either Notify(VGA, 0x81) or Notify(VGA, n) 223254885Sdumbbell * where n is specified in the result if a notifier is used. 224254885Sdumbbell * Returns 0 on success, error on failure. 225254885Sdumbbell */ 226254885Sdumbbellstatic int radeon_atif_get_notification_params(ACPI_HANDLE handle, 227254885Sdumbbell struct radeon_atif_notification_cfg *n) 228254885Sdumbbell{ 229254885Sdumbbell ACPI_OBJECT *info; 230254885Sdumbbell struct atif_system_params params; 231254885Sdumbbell size_t size; 232254885Sdumbbell int err = 0; 233254885Sdumbbell 234254885Sdumbbell info = radeon_atif_call(handle, ATIF_FUNCTION_GET_SYSTEM_PARAMETERS, NULL); 235254885Sdumbbell if (!info) { 236254885Sdumbbell err = -EIO; 237254885Sdumbbell goto out; 238254885Sdumbbell } 239254885Sdumbbell 240254885Sdumbbell size = *(u16 *) info->Buffer.Pointer; 241254885Sdumbbell if (size < 10) { 242254885Sdumbbell err = -EINVAL; 243254885Sdumbbell goto out; 244254885Sdumbbell } 245254885Sdumbbell 246254885Sdumbbell memset(¶ms, 0, sizeof(params)); 247254885Sdumbbell size = min(sizeof(params), size); 248254885Sdumbbell memcpy(¶ms, info->Buffer.Pointer, size); 249254885Sdumbbell 250254885Sdumbbell DRM_DEBUG_DRIVER("SYSTEM_PARAMS: mask = %#x, flags = %#x\n", 251254885Sdumbbell params.flags, params.valid_mask); 252254885Sdumbbell params.flags = params.flags & params.valid_mask; 253254885Sdumbbell 254254885Sdumbbell if ((params.flags & ATIF_NOTIFY_MASK) == ATIF_NOTIFY_NONE) { 255254885Sdumbbell n->enabled = false; 256254885Sdumbbell n->command_code = 0; 257254885Sdumbbell } else if ((params.flags & ATIF_NOTIFY_MASK) == ATIF_NOTIFY_81) { 258254885Sdumbbell n->enabled = true; 259254885Sdumbbell n->command_code = 0x81; 260254885Sdumbbell } else { 261254885Sdumbbell if (size < 11) { 262254885Sdumbbell err = -EINVAL; 263254885Sdumbbell goto out; 264254885Sdumbbell } 265254885Sdumbbell n->enabled = true; 266254885Sdumbbell n->command_code = params.command_code; 267254885Sdumbbell } 268254885Sdumbbell 269254885Sdumbbellout: 270254885Sdumbbell DRM_DEBUG_DRIVER("Notification %s, command code = %#x\n", 271254885Sdumbbell (n->enabled ? "enabled" : "disabled"), 272254885Sdumbbell n->command_code); 273254885Sdumbbell AcpiOsFree(info); 274254885Sdumbbell return err; 275254885Sdumbbell} 276254885Sdumbbell 277254885Sdumbbell/** 278254885Sdumbbell * radeon_atif_get_sbios_requests - get requested sbios event 279254885Sdumbbell * 280254885Sdumbbell * @handle: acpi handle 281254885Sdumbbell * @req: atif sbios request struct 282254885Sdumbbell * 283254885Sdumbbell * Execute the ATIF_FUNCTION_GET_SYSTEM_BIOS_REQUESTS ATIF function 284254885Sdumbbell * to determine what requests the sbios is making to the driver 285254885Sdumbbell * (all asics). 286254885Sdumbbell * Returns 0 on success, error on failure. 287254885Sdumbbell */ 288254885Sdumbbellstatic int radeon_atif_get_sbios_requests(ACPI_HANDLE handle, 289254885Sdumbbell struct atif_sbios_requests *req) 290254885Sdumbbell{ 291254885Sdumbbell ACPI_OBJECT *info; 292254885Sdumbbell size_t size; 293254885Sdumbbell int count = 0; 294254885Sdumbbell 295254885Sdumbbell info = radeon_atif_call(handle, ATIF_FUNCTION_GET_SYSTEM_BIOS_REQUESTS, NULL); 296254885Sdumbbell if (!info) 297254885Sdumbbell return -EIO; 298254885Sdumbbell 299254885Sdumbbell size = *(u16 *)info->Buffer.Pointer; 300254885Sdumbbell if (size < 0xd) { 301254885Sdumbbell count = -EINVAL; 302254885Sdumbbell goto out; 303254885Sdumbbell } 304254885Sdumbbell memset(req, 0, sizeof(*req)); 305254885Sdumbbell 306254885Sdumbbell size = min(sizeof(*req), size); 307254885Sdumbbell memcpy(req, info->Buffer.Pointer, size); 308254885Sdumbbell DRM_DEBUG_DRIVER("SBIOS pending requests: %#x\n", req->pending); 309254885Sdumbbell 310254885Sdumbbell count = hweight32(req->pending); 311254885Sdumbbell 312254885Sdumbbellout: 313254885Sdumbbell AcpiOsFree(info); 314254885Sdumbbell return count; 315254885Sdumbbell} 316254885Sdumbbell 317254885Sdumbbell/** 318254885Sdumbbell * radeon_atif_handler - handle ATIF notify requests 319254885Sdumbbell * 320254885Sdumbbell * @rdev: radeon_device pointer 321254885Sdumbbell * @event: atif sbios request struct 322254885Sdumbbell * 323254885Sdumbbell * Checks the acpi event and if it matches an atif event, 324254885Sdumbbell * handles it. 325254885Sdumbbell * Returns NOTIFY code 326254885Sdumbbell */ 327254885Sdumbbellvoid radeon_atif_handler(struct radeon_device *rdev, 328254885Sdumbbell UINT32 type) 329254885Sdumbbell{ 330254885Sdumbbell struct radeon_atif *atif = &rdev->atif; 331254885Sdumbbell struct atif_sbios_requests req; 332254885Sdumbbell ACPI_HANDLE handle; 333254885Sdumbbell int count; 334254885Sdumbbell 335254885Sdumbbell DRM_DEBUG_DRIVER("event, type = %#x\n", 336254885Sdumbbell type); 337254885Sdumbbell 338254885Sdumbbell if (!atif->notification_cfg.enabled || 339254885Sdumbbell type != atif->notification_cfg.command_code) 340254885Sdumbbell /* Not our event */ 341254885Sdumbbell return; 342254885Sdumbbell 343254885Sdumbbell /* Check pending SBIOS requests */ 344254885Sdumbbell handle = rdev->acpi.handle; 345254885Sdumbbell count = radeon_atif_get_sbios_requests(handle, &req); 346254885Sdumbbell 347254885Sdumbbell if (count <= 0) 348254885Sdumbbell return; 349254885Sdumbbell 350254885Sdumbbell DRM_DEBUG_DRIVER("ATIF: %d pending SBIOS requests\n", count); 351254885Sdumbbell 352254885Sdumbbell if (req.pending & ATIF_PANEL_BRIGHTNESS_CHANGE_REQUEST) { 353254885Sdumbbell struct radeon_encoder *enc = atif->encoder_for_bl; 354254885Sdumbbell 355254885Sdumbbell if (enc) { 356254885Sdumbbell DRM_DEBUG_DRIVER("Changing brightness to %d\n", 357254885Sdumbbell req.backlight_level); 358254885Sdumbbell 359254885Sdumbbell radeon_set_backlight_level(rdev, enc, req.backlight_level); 360254885Sdumbbell 361254885Sdumbbell#ifdef DUMBBELL_WIP 362254885Sdumbbell if (rdev->is_atom_bios) { 363254885Sdumbbell struct radeon_encoder_atom_dig *dig = enc->enc_priv; 364254885Sdumbbell backlight_force_update(dig->bl_dev, 365254885Sdumbbell BACKLIGHT_UPDATE_HOTKEY); 366254885Sdumbbell } else { 367254885Sdumbbell struct radeon_encoder_lvds *dig = enc->enc_priv; 368254885Sdumbbell backlight_force_update(dig->bl_dev, 369254885Sdumbbell BACKLIGHT_UPDATE_HOTKEY); 370254885Sdumbbell } 371254885Sdumbbell#endif /* DUMBBELL_WIP */ 372254885Sdumbbell } 373254885Sdumbbell } 374254885Sdumbbell /* TODO: check other events */ 375254885Sdumbbell 376254885Sdumbbell /* We've handled the event, stop the notifier chain. The ACPI interface 377254885Sdumbbell * overloads ACPI_VIDEO_NOTIFY_PROBE, we don't want to send that to 378254885Sdumbbell * userspace if the event was generated only to signal a SBIOS 379254885Sdumbbell * request. 380254885Sdumbbell */ 381254885Sdumbbell} 382254885Sdumbbell 383254885Sdumbbell/* Call the ATCS method 384254885Sdumbbell */ 385254885Sdumbbell/** 386254885Sdumbbell * radeon_atcs_call - call an ATCS method 387254885Sdumbbell * 388254885Sdumbbell * @handle: acpi handle 389254885Sdumbbell * @function: the ATCS function to execute 390254885Sdumbbell * @params: ATCS function params 391254885Sdumbbell * 392254885Sdumbbell * Executes the requested ATCS function (all asics). 393254885Sdumbbell * Returns a pointer to the acpi output buffer. 394254885Sdumbbell */ 395254885Sdumbbellstatic union acpi_object *radeon_atcs_call(ACPI_HANDLE handle, int function, 396254885Sdumbbell ACPI_BUFFER *params) 397254885Sdumbbell{ 398254885Sdumbbell ACPI_STATUS status; 399254885Sdumbbell ACPI_OBJECT atcs_arg_elements[2]; 400254885Sdumbbell ACPI_OBJECT_LIST atcs_arg; 401254885Sdumbbell ACPI_BUFFER buffer = { ACPI_ALLOCATE_BUFFER, NULL }; 402254885Sdumbbell 403254885Sdumbbell atcs_arg.Count = 2; 404254885Sdumbbell atcs_arg.Pointer = &atcs_arg_elements[0]; 405254885Sdumbbell 406254885Sdumbbell atcs_arg_elements[0].Type = ACPI_TYPE_INTEGER; 407254885Sdumbbell atcs_arg_elements[0].Integer.Value = function; 408254885Sdumbbell 409254885Sdumbbell if (params) { 410254885Sdumbbell atcs_arg_elements[1].Type = ACPI_TYPE_BUFFER; 411254885Sdumbbell atcs_arg_elements[1].Buffer.Length = params->Length; 412254885Sdumbbell atcs_arg_elements[1].Buffer.Pointer = params->Pointer; 413254885Sdumbbell } else { 414254885Sdumbbell /* We need a second fake parameter */ 415254885Sdumbbell atcs_arg_elements[1].Type = ACPI_TYPE_INTEGER; 416254885Sdumbbell atcs_arg_elements[1].Integer.Value = 0; 417254885Sdumbbell } 418254885Sdumbbell 419254885Sdumbbell status = AcpiEvaluateObject(handle, "ATCS", &atcs_arg, &buffer); 420254885Sdumbbell 421254885Sdumbbell /* Fail only if calling the method fails and ATIF is supported */ 422254885Sdumbbell if (ACPI_FAILURE(status) && status != AE_NOT_FOUND) { 423254885Sdumbbell DRM_DEBUG_DRIVER("failed to evaluate ATCS got %s\n", 424254885Sdumbbell AcpiFormatException(status)); 425254885Sdumbbell AcpiOsFree(buffer.Pointer); 426254885Sdumbbell return NULL; 427254885Sdumbbell } 428254885Sdumbbell 429254885Sdumbbell return buffer.Pointer; 430254885Sdumbbell} 431254885Sdumbbell 432254885Sdumbbell/** 433254885Sdumbbell * radeon_atcs_parse_functions - parse supported functions 434254885Sdumbbell * 435254885Sdumbbell * @f: supported functions struct 436254885Sdumbbell * @mask: supported functions mask from ATCS 437254885Sdumbbell * 438254885Sdumbbell * Use the supported functions mask from ATCS function 439254885Sdumbbell * ATCS_FUNCTION_VERIFY_INTERFACE to determine what functions 440254885Sdumbbell * are supported (all asics). 441254885Sdumbbell */ 442254885Sdumbbellstatic void radeon_atcs_parse_functions(struct radeon_atcs_functions *f, u32 mask) 443254885Sdumbbell{ 444254885Sdumbbell f->get_ext_state = mask & ATCS_GET_EXTERNAL_STATE_SUPPORTED; 445254885Sdumbbell f->pcie_perf_req = mask & ATCS_PCIE_PERFORMANCE_REQUEST_SUPPORTED; 446254885Sdumbbell f->pcie_dev_rdy = mask & ATCS_PCIE_DEVICE_READY_NOTIFICATION_SUPPORTED; 447254885Sdumbbell f->pcie_bus_width = mask & ATCS_SET_PCIE_BUS_WIDTH_SUPPORTED; 448254885Sdumbbell} 449254885Sdumbbell 450254885Sdumbbell/** 451254885Sdumbbell * radeon_atcs_verify_interface - verify ATCS 452254885Sdumbbell * 453254885Sdumbbell * @handle: acpi handle 454254885Sdumbbell * @atcs: radeon atcs struct 455254885Sdumbbell * 456254885Sdumbbell * Execute the ATCS_FUNCTION_VERIFY_INTERFACE ATCS function 457254885Sdumbbell * to initialize ATCS and determine what features are supported 458254885Sdumbbell * (all asics). 459254885Sdumbbell * returns 0 on success, error on failure. 460254885Sdumbbell */ 461254885Sdumbbellstatic int radeon_atcs_verify_interface(ACPI_HANDLE handle, 462254885Sdumbbell struct radeon_atcs *atcs) 463254885Sdumbbell{ 464254885Sdumbbell ACPI_OBJECT *info; 465254885Sdumbbell struct atcs_verify_interface output; 466254885Sdumbbell size_t size; 467254885Sdumbbell int err = 0; 468254885Sdumbbell 469254885Sdumbbell info = radeon_atcs_call(handle, ATCS_FUNCTION_VERIFY_INTERFACE, NULL); 470254885Sdumbbell if (!info) 471254885Sdumbbell return -EIO; 472254885Sdumbbell 473254885Sdumbbell memset(&output, 0, sizeof(output)); 474254885Sdumbbell 475254885Sdumbbell size = *(u16 *) info->Buffer.Pointer; 476254885Sdumbbell if (size < 8) { 477254885Sdumbbell DRM_INFO("ATCS buffer is too small: %zu\n", size); 478254885Sdumbbell err = -EINVAL; 479254885Sdumbbell goto out; 480254885Sdumbbell } 481254885Sdumbbell size = min(sizeof(output), size); 482254885Sdumbbell 483254885Sdumbbell memcpy(&output, info->Buffer.Pointer, size); 484254885Sdumbbell 485254885Sdumbbell /* TODO: check version? */ 486254885Sdumbbell DRM_DEBUG_DRIVER("ATCS version %u\n", output.version); 487254885Sdumbbell 488254885Sdumbbell radeon_atcs_parse_functions(&atcs->functions, output.function_bits); 489254885Sdumbbell 490254885Sdumbbellout: 491254885Sdumbbell AcpiOsFree(info); 492254885Sdumbbell return err; 493254885Sdumbbell} 494254885Sdumbbell 495254885Sdumbbell/** 496254885Sdumbbell * radeon_acpi_event - handle notify events 497254885Sdumbbell * 498254885Sdumbbell * @nb: notifier block 499254885Sdumbbell * @val: val 500254885Sdumbbell * @data: acpi event 501254885Sdumbbell * 502254885Sdumbbell * Calls relevant radeon functions in response to various 503254885Sdumbbell * acpi events. 504254885Sdumbbell * Returns NOTIFY code 505254885Sdumbbell */ 506254885Sdumbbellstatic void radeon_acpi_event(ACPI_HANDLE handle, UINT32 type, 507254885Sdumbbell void *context) 508254885Sdumbbell{ 509254885Sdumbbell struct radeon_device *rdev = (struct radeon_device *)context; 510254885Sdumbbell 511254885Sdumbbell#ifdef DUMBBELL_WIP 512254885Sdumbbell if (strcmp(entry->device_class, ACPI_AC_CLASS) == 0) { 513254885Sdumbbell if (power_supply_is_system_supplied() > 0) 514254885Sdumbbell DRM_DEBUG_DRIVER("pm: AC\n"); 515254885Sdumbbell else 516254885Sdumbbell DRM_DEBUG_DRIVER("pm: DC\n"); 517254885Sdumbbell 518254885Sdumbbell radeon_pm_acpi_event_handler(rdev); 519254885Sdumbbell } 520254885Sdumbbell#endif /* DUMBBELL_WIP */ 521254885Sdumbbell 522254885Sdumbbell /* Check for pending SBIOS requests */ 523254885Sdumbbell radeon_atif_handler(rdev, type); 524254885Sdumbbell} 525254885Sdumbbell 526254885Sdumbbell/* Call all ACPI methods here */ 527254885Sdumbbell/** 528254885Sdumbbell * radeon_acpi_init - init driver acpi support 529254885Sdumbbell * 530254885Sdumbbell * @rdev: radeon_device pointer 531254885Sdumbbell * 532254885Sdumbbell * Verifies the AMD ACPI interfaces and registers with the acpi 533254885Sdumbbell * notifier chain (all asics). 534254885Sdumbbell * Returns 0 on success, error on failure. 535254885Sdumbbell */ 536254885Sdumbbellint radeon_acpi_init(struct radeon_device *rdev) 537254885Sdumbbell{ 538254885Sdumbbell ACPI_HANDLE handle; 539254885Sdumbbell struct radeon_atif *atif = &rdev->atif; 540254885Sdumbbell struct radeon_atcs *atcs = &rdev->atcs; 541254885Sdumbbell int ret; 542254885Sdumbbell 543254885Sdumbbell /* Get the device handle */ 544254885Sdumbbell handle = acpi_get_handle(rdev->dev); 545254885Sdumbbell 546254885Sdumbbell /* No need to proceed if we're sure that ATIF is not supported */ 547254885Sdumbbell if (!ASIC_IS_AVIVO(rdev) || !rdev->bios || !handle) 548254885Sdumbbell return 0; 549254885Sdumbbell 550254885Sdumbbell /* Call the ATCS method */ 551254885Sdumbbell ret = radeon_atcs_verify_interface(handle, atcs); 552254885Sdumbbell if (ret) { 553254885Sdumbbell DRM_DEBUG_DRIVER("Call to ATCS verify_interface failed: %d\n", ret); 554254885Sdumbbell } 555254885Sdumbbell 556254885Sdumbbell /* Call the ATIF method */ 557254885Sdumbbell ret = radeon_atif_verify_interface(handle, atif); 558254885Sdumbbell if (ret) { 559254885Sdumbbell DRM_DEBUG_DRIVER("Call to ATIF verify_interface failed: %d\n", ret); 560254885Sdumbbell goto out; 561254885Sdumbbell } 562254885Sdumbbell 563254885Sdumbbell if (atif->notifications.brightness_change) { 564254885Sdumbbell struct drm_encoder *tmp; 565254885Sdumbbell struct radeon_encoder *target = NULL; 566254885Sdumbbell 567254885Sdumbbell /* Find the encoder controlling the brightness */ 568254885Sdumbbell list_for_each_entry(tmp, &rdev->ddev->mode_config.encoder_list, 569254885Sdumbbell head) { 570254885Sdumbbell struct radeon_encoder *enc = to_radeon_encoder(tmp); 571254885Sdumbbell 572254885Sdumbbell if ((enc->devices & (ATOM_DEVICE_LCD_SUPPORT)) && 573254885Sdumbbell enc->enc_priv) { 574254885Sdumbbell if (rdev->is_atom_bios) { 575254885Sdumbbell struct radeon_encoder_atom_dig *dig = enc->enc_priv; 576254885Sdumbbell if (dig->bl_dev) { 577254885Sdumbbell target = enc; 578254885Sdumbbell break; 579254885Sdumbbell } 580254885Sdumbbell } else { 581254885Sdumbbell struct radeon_encoder_lvds *dig = enc->enc_priv; 582254885Sdumbbell if (dig->bl_dev) { 583254885Sdumbbell target = enc; 584254885Sdumbbell break; 585254885Sdumbbell } 586254885Sdumbbell } 587254885Sdumbbell } 588254885Sdumbbell } 589254885Sdumbbell 590254885Sdumbbell atif->encoder_for_bl = target; 591254885Sdumbbell if (!target) { 592254885Sdumbbell /* Brightness change notification is enabled, but we 593254885Sdumbbell * didn't find a backlight controller, this should 594254885Sdumbbell * never happen. 595254885Sdumbbell */ 596254885Sdumbbell DRM_ERROR("Cannot find a backlight controller\n"); 597254885Sdumbbell } 598254885Sdumbbell } 599254885Sdumbbell 600254885Sdumbbell if (atif->functions.sbios_requests && !atif->functions.system_params) { 601254885Sdumbbell /* XXX check this workraround, if sbios request function is 602254885Sdumbbell * present we have to see how it's configured in the system 603254885Sdumbbell * params 604254885Sdumbbell */ 605254885Sdumbbell atif->functions.system_params = true; 606254885Sdumbbell } 607254885Sdumbbell 608254885Sdumbbell if (atif->functions.system_params) { 609254885Sdumbbell ret = radeon_atif_get_notification_params(handle, 610254885Sdumbbell &atif->notification_cfg); 611254885Sdumbbell if (ret) { 612254885Sdumbbell DRM_DEBUG_DRIVER("Call to GET_SYSTEM_PARAMS failed: %d\n", 613254885Sdumbbell ret); 614254885Sdumbbell /* Disable notification */ 615254885Sdumbbell atif->notification_cfg.enabled = false; 616254885Sdumbbell } 617254885Sdumbbell } 618254885Sdumbbell 619254885Sdumbbellout: 620254885Sdumbbell rdev->acpi.handle = handle; 621254885Sdumbbell rdev->acpi.notifier_call = radeon_acpi_event; 622254885Sdumbbell AcpiInstallNotifyHandler(handle, ACPI_DEVICE_NOTIFY, 623254885Sdumbbell rdev->acpi.notifier_call, rdev); 624254885Sdumbbell 625254885Sdumbbell return ret; 626254885Sdumbbell} 627254885Sdumbbell 628254885Sdumbbell/** 629254885Sdumbbell * radeon_acpi_fini - tear down driver acpi support 630254885Sdumbbell * 631254885Sdumbbell * @rdev: radeon_device pointer 632254885Sdumbbell * 633254885Sdumbbell * Unregisters with the acpi notifier chain (all asics). 634254885Sdumbbell */ 635254885Sdumbbellvoid radeon_acpi_fini(struct radeon_device *rdev) 636254885Sdumbbell{ 637254885Sdumbbell AcpiRemoveNotifyHandler(rdev->acpi.handle, ACPI_DEVICE_NOTIFY, 638254885Sdumbbell rdev->acpi.notifier_call); 639254885Sdumbbell} 640