1efd4e418SAlex Deucher /* 2efd4e418SAlex Deucher * Copyright 2012 Advanced Micro Devices, Inc. 3efd4e418SAlex Deucher * 4efd4e418SAlex Deucher * Permission is hereby granted, free of charge, to any person obtaining a 5efd4e418SAlex Deucher * copy of this software and associated documentation files (the "Software"), 6efd4e418SAlex Deucher * to deal in the Software without restriction, including without limitation 7efd4e418SAlex Deucher * the rights to use, copy, modify, merge, publish, distribute, sublicense, 8efd4e418SAlex Deucher * and/or sell copies of the Software, and to permit persons to whom the 9efd4e418SAlex Deucher * Software is furnished to do so, subject to the following conditions: 10efd4e418SAlex Deucher * 11efd4e418SAlex Deucher * The above copyright notice and this permission notice shall be included in 12efd4e418SAlex Deucher * all copies or substantial portions of the Software. 13efd4e418SAlex Deucher * 14efd4e418SAlex Deucher * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 15efd4e418SAlex Deucher * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 16efd4e418SAlex Deucher * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL 17efd4e418SAlex Deucher * THE COPYRIGHT HOLDER(S) OR AUTHOR(S) BE LIABLE FOR ANY CLAIM, DAMAGES OR 18efd4e418SAlex Deucher * OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, 19efd4e418SAlex Deucher * ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR 20efd4e418SAlex Deucher * OTHER DEALINGS IN THE SOFTWARE. 21efd4e418SAlex Deucher * 22efd4e418SAlex Deucher */ 23efd4e418SAlex Deucher 24d7a2952fSAlberto Milone #include <linux/pci.h> 25d7a2952fSAlberto Milone #include <linux/acpi.h> 26d7a2952fSAlberto Milone #include <linux/slab.h> 27d7a2952fSAlberto Milone #include <acpi/acpi_drivers.h> 28d7a2952fSAlberto Milone #include <acpi/acpi_bus.h> 29*fda4b25cSLuca Tettamanti #include <acpi/video.h> 30d7a2952fSAlberto Milone 31d7a2952fSAlberto Milone #include "drmP.h" 32d7a2952fSAlberto Milone #include "drm.h" 33d7a2952fSAlberto Milone #include "drm_sarea.h" 34d7a2952fSAlberto Milone #include "drm_crtc_helper.h" 35d7a2952fSAlberto Milone #include "radeon.h" 369e05b2f4SAlex Deucher #include "radeon_acpi.h" 37*fda4b25cSLuca Tettamanti #include "atom.h" 38d7a2952fSAlberto Milone 39d7a2952fSAlberto Milone #include <linux/vga_switcheroo.h> 40d7a2952fSAlberto Milone 41fd64ca8aSLuca Tettamanti struct atif_verify_interface { 42fd64ca8aSLuca Tettamanti u16 size; /* structure size in bytes (includes size field) */ 43fd64ca8aSLuca Tettamanti u16 version; /* version */ 44fd64ca8aSLuca Tettamanti u32 notification_mask; /* supported notifications mask */ 45fd64ca8aSLuca Tettamanti u32 function_bits; /* supported functions bit vector */ 46fd64ca8aSLuca Tettamanti } __packed; 47fd64ca8aSLuca Tettamanti 48ce3cf821SLuca Tettamanti struct atif_system_params { 49*fda4b25cSLuca Tettamanti u16 size; /* structure size in bytes (includes size field) */ 50*fda4b25cSLuca Tettamanti u32 valid_mask; /* valid flags mask */ 51*fda4b25cSLuca Tettamanti u32 flags; /* flags */ 52*fda4b25cSLuca Tettamanti u8 command_code; /* notify command code */ 53*fda4b25cSLuca Tettamanti } __packed; 54*fda4b25cSLuca Tettamanti 55*fda4b25cSLuca Tettamanti struct atif_sbios_requests { 56*fda4b25cSLuca Tettamanti u16 size; /* structure size in bytes (includes size field) */ 57*fda4b25cSLuca Tettamanti u32 pending; /* pending sbios requests */ 58*fda4b25cSLuca Tettamanti u8 panel_exp_mode; /* panel expansion mode */ 59*fda4b25cSLuca Tettamanti u8 thermal_gfx; /* thermal state: target gfx controller */ 60*fda4b25cSLuca Tettamanti u8 thermal_state; /* thermal state: state id (0: exit state, non-0: state) */ 61*fda4b25cSLuca Tettamanti u8 forced_power_gfx; /* forced power state: target gfx controller */ 62*fda4b25cSLuca Tettamanti u8 forced_power_state; /* forced power state: state id */ 63*fda4b25cSLuca Tettamanti u8 system_power_src; /* system power source */ 64*fda4b25cSLuca Tettamanti u8 backlight_level; /* panel backlight level (0-255) */ 65ce3cf821SLuca Tettamanti } __packed; 66ce3cf821SLuca Tettamanti 67ce3cf821SLuca Tettamanti #define ATIF_NOTIFY_MASK 0x3 68ce3cf821SLuca Tettamanti #define ATIF_NOTIFY_NONE 0 69ce3cf821SLuca Tettamanti #define ATIF_NOTIFY_81 1 70ce3cf821SLuca Tettamanti #define ATIF_NOTIFY_N 2 71ce3cf821SLuca Tettamanti 72d7a2952fSAlberto Milone /* Call the ATIF method 73d7a2952fSAlberto Milone */ 7486504672SLuca Tettamanti static union acpi_object *radeon_atif_call(acpi_handle handle, int function, 7586504672SLuca Tettamanti struct acpi_buffer *params) 76d7a2952fSAlberto Milone { 77d7a2952fSAlberto Milone acpi_status status; 78d7a2952fSAlberto Milone union acpi_object atif_arg_elements[2]; 79d7a2952fSAlberto Milone struct acpi_object_list atif_arg; 80d7a2952fSAlberto Milone struct acpi_buffer buffer = { ACPI_ALLOCATE_BUFFER, NULL }; 81d7a2952fSAlberto Milone 82d7a2952fSAlberto Milone atif_arg.count = 2; 83d7a2952fSAlberto Milone atif_arg.pointer = &atif_arg_elements[0]; 84d7a2952fSAlberto Milone 85d7a2952fSAlberto Milone atif_arg_elements[0].type = ACPI_TYPE_INTEGER; 8686504672SLuca Tettamanti atif_arg_elements[0].integer.value = function; 8786504672SLuca Tettamanti 8886504672SLuca Tettamanti if (params) { 8986504672SLuca Tettamanti atif_arg_elements[1].type = ACPI_TYPE_BUFFER; 9086504672SLuca Tettamanti atif_arg_elements[1].buffer.length = params->length; 9186504672SLuca Tettamanti atif_arg_elements[1].buffer.pointer = params->pointer; 9286504672SLuca Tettamanti } else { 9386504672SLuca Tettamanti /* We need a second fake parameter */ 94d7a2952fSAlberto Milone atif_arg_elements[1].type = ACPI_TYPE_INTEGER; 95d7a2952fSAlberto Milone atif_arg_elements[1].integer.value = 0; 9686504672SLuca Tettamanti } 97d7a2952fSAlberto Milone 98d7a2952fSAlberto Milone status = acpi_evaluate_object(handle, "ATIF", &atif_arg, &buffer); 99d7a2952fSAlberto Milone 100d7a2952fSAlberto Milone /* Fail only if calling the method fails and ATIF is supported */ 101d7a2952fSAlberto Milone if (ACPI_FAILURE(status) && status != AE_NOT_FOUND) { 102bc96f942SJean Delvare DRM_DEBUG_DRIVER("failed to evaluate ATIF got %s\n", 103bc96f942SJean Delvare acpi_format_exception(status)); 104d7a2952fSAlberto Milone kfree(buffer.pointer); 10586504672SLuca Tettamanti return NULL; 106d7a2952fSAlberto Milone } 107d7a2952fSAlberto Milone 10886504672SLuca Tettamanti return buffer.pointer; 109d7a2952fSAlberto Milone } 110d7a2952fSAlberto Milone 111fd64ca8aSLuca Tettamanti static void radeon_atif_parse_notification(struct radeon_atif_notifications *n, u32 mask) 112fd64ca8aSLuca Tettamanti { 113fd64ca8aSLuca Tettamanti n->display_switch = mask & ATIF_DISPLAY_SWITCH_REQUEST_SUPPORTED; 114fd64ca8aSLuca Tettamanti n->expansion_mode_change = mask & ATIF_EXPANSION_MODE_CHANGE_REQUEST_SUPPORTED; 115fd64ca8aSLuca Tettamanti n->thermal_state = mask & ATIF_THERMAL_STATE_CHANGE_REQUEST_SUPPORTED; 116fd64ca8aSLuca Tettamanti n->forced_power_state = mask & ATIF_FORCED_POWER_STATE_CHANGE_REQUEST_SUPPORTED; 117fd64ca8aSLuca Tettamanti n->system_power_state = mask & ATIF_SYSTEM_POWER_SOURCE_CHANGE_REQUEST_SUPPORTED; 118fd64ca8aSLuca Tettamanti n->display_conf_change = mask & ATIF_DISPLAY_CONF_CHANGE_REQUEST_SUPPORTED; 119fd64ca8aSLuca Tettamanti n->px_gfx_switch = mask & ATIF_PX_GFX_SWITCH_REQUEST_SUPPORTED; 120fd64ca8aSLuca Tettamanti n->brightness_change = mask & ATIF_PANEL_BRIGHTNESS_CHANGE_REQUEST_SUPPORTED; 121fd64ca8aSLuca Tettamanti n->dgpu_display_event = mask & ATIF_DGPU_DISPLAY_EVENT_SUPPORTED; 122fd64ca8aSLuca Tettamanti } 123fd64ca8aSLuca Tettamanti 124fd64ca8aSLuca Tettamanti static void radeon_atif_parse_functions(struct radeon_atif_functions *f, u32 mask) 125fd64ca8aSLuca Tettamanti { 126fd64ca8aSLuca Tettamanti f->system_params = mask & ATIF_GET_SYSTEM_PARAMETERS_SUPPORTED; 127fd64ca8aSLuca Tettamanti f->sbios_requests = mask & ATIF_GET_SYSTEM_BIOS_REQUESTS_SUPPORTED; 128fd64ca8aSLuca Tettamanti f->select_active_disp = mask & ATIF_SELECT_ACTIVE_DISPLAYS_SUPPORTED; 129fd64ca8aSLuca Tettamanti f->lid_state = mask & ATIF_GET_LID_STATE_SUPPORTED; 130fd64ca8aSLuca Tettamanti f->get_tv_standard = mask & ATIF_GET_TV_STANDARD_FROM_CMOS_SUPPORTED; 131fd64ca8aSLuca Tettamanti f->set_tv_standard = mask & ATIF_SET_TV_STANDARD_IN_CMOS_SUPPORTED; 132fd64ca8aSLuca Tettamanti f->get_panel_expansion_mode = mask & ATIF_GET_PANEL_EXPANSION_MODE_FROM_CMOS_SUPPORTED; 133fd64ca8aSLuca Tettamanti f->set_panel_expansion_mode = mask & ATIF_SET_PANEL_EXPANSION_MODE_IN_CMOS_SUPPORTED; 134fd64ca8aSLuca Tettamanti f->temperature_change = mask & ATIF_TEMPERATURE_CHANGE_NOTIFICATION_SUPPORTED; 135fd64ca8aSLuca Tettamanti f->graphics_device_types = mask & ATIF_GET_GRAPHICS_DEVICE_TYPES_SUPPORTED; 136fd64ca8aSLuca Tettamanti } 137fd64ca8aSLuca Tettamanti 138fd64ca8aSLuca Tettamanti static int radeon_atif_verify_interface(acpi_handle handle, 139fd64ca8aSLuca Tettamanti struct radeon_atif *atif) 140fd64ca8aSLuca Tettamanti { 141fd64ca8aSLuca Tettamanti union acpi_object *info; 142fd64ca8aSLuca Tettamanti struct atif_verify_interface output; 143fd64ca8aSLuca Tettamanti size_t size; 144fd64ca8aSLuca Tettamanti int err = 0; 145fd64ca8aSLuca Tettamanti 146fd64ca8aSLuca Tettamanti info = radeon_atif_call(handle, ATIF_FUNCTION_VERIFY_INTERFACE, NULL); 147fd64ca8aSLuca Tettamanti if (!info) 148fd64ca8aSLuca Tettamanti return -EIO; 149fd64ca8aSLuca Tettamanti 150fd64ca8aSLuca Tettamanti memset(&output, 0, sizeof(output)); 151fd64ca8aSLuca Tettamanti 152fd64ca8aSLuca Tettamanti size = *(u16 *) info->buffer.pointer; 153fd64ca8aSLuca Tettamanti if (size < 12) { 154fd64ca8aSLuca Tettamanti DRM_INFO("ATIF buffer is too small: %lu\n", size); 155fd64ca8aSLuca Tettamanti err = -EINVAL; 156fd64ca8aSLuca Tettamanti goto out; 157fd64ca8aSLuca Tettamanti } 158fd64ca8aSLuca Tettamanti size = min(sizeof(output), size); 159fd64ca8aSLuca Tettamanti 160fd64ca8aSLuca Tettamanti memcpy(&output, info->buffer.pointer, size); 161fd64ca8aSLuca Tettamanti 162fd64ca8aSLuca Tettamanti /* TODO: check version? */ 163fd64ca8aSLuca Tettamanti DRM_DEBUG_DRIVER("ATIF version %u\n", output.version); 164fd64ca8aSLuca Tettamanti 165fd64ca8aSLuca Tettamanti radeon_atif_parse_notification(&atif->notifications, output.notification_mask); 166fd64ca8aSLuca Tettamanti radeon_atif_parse_functions(&atif->functions, output.function_bits); 167fd64ca8aSLuca Tettamanti 168fd64ca8aSLuca Tettamanti out: 169fd64ca8aSLuca Tettamanti kfree(info); 170fd64ca8aSLuca Tettamanti return err; 171fd64ca8aSLuca Tettamanti } 172fd64ca8aSLuca Tettamanti 173ce3cf821SLuca Tettamanti static int radeon_atif_get_notification_params(acpi_handle handle, 174ce3cf821SLuca Tettamanti struct radeon_atif_notification_cfg *n) 175ce3cf821SLuca Tettamanti { 176ce3cf821SLuca Tettamanti union acpi_object *info; 177ce3cf821SLuca Tettamanti struct atif_system_params params; 178ce3cf821SLuca Tettamanti size_t size; 179ce3cf821SLuca Tettamanti int err = 0; 180ce3cf821SLuca Tettamanti 181ce3cf821SLuca Tettamanti info = radeon_atif_call(handle, ATIF_FUNCTION_GET_SYSTEM_PARAMETERS, NULL); 182ce3cf821SLuca Tettamanti if (!info) { 183ce3cf821SLuca Tettamanti err = -EIO; 184ce3cf821SLuca Tettamanti goto out; 185ce3cf821SLuca Tettamanti } 186ce3cf821SLuca Tettamanti 187ce3cf821SLuca Tettamanti size = *(u16 *) info->buffer.pointer; 188ce3cf821SLuca Tettamanti if (size < 10) { 189ce3cf821SLuca Tettamanti err = -EINVAL; 190ce3cf821SLuca Tettamanti goto out; 191ce3cf821SLuca Tettamanti } 192ce3cf821SLuca Tettamanti 193ce3cf821SLuca Tettamanti memset(¶ms, 0, sizeof(params)); 194ce3cf821SLuca Tettamanti size = min(sizeof(params), size); 195ce3cf821SLuca Tettamanti memcpy(¶ms, info->buffer.pointer, size); 196ce3cf821SLuca Tettamanti 197*fda4b25cSLuca Tettamanti DRM_DEBUG_DRIVER("SYSTEM_PARAMS: mask = %#x, flags = %#x\n", 198*fda4b25cSLuca Tettamanti params.flags, params.valid_mask); 199ce3cf821SLuca Tettamanti params.flags = params.flags & params.valid_mask; 200ce3cf821SLuca Tettamanti 201ce3cf821SLuca Tettamanti if ((params.flags & ATIF_NOTIFY_MASK) == ATIF_NOTIFY_NONE) { 202ce3cf821SLuca Tettamanti n->enabled = false; 203ce3cf821SLuca Tettamanti n->command_code = 0; 204ce3cf821SLuca Tettamanti } else if ((params.flags & ATIF_NOTIFY_MASK) == ATIF_NOTIFY_81) { 205ce3cf821SLuca Tettamanti n->enabled = true; 206ce3cf821SLuca Tettamanti n->command_code = 0x81; 207ce3cf821SLuca Tettamanti } else { 208ce3cf821SLuca Tettamanti if (size < 11) { 209ce3cf821SLuca Tettamanti err = -EINVAL; 210ce3cf821SLuca Tettamanti goto out; 211ce3cf821SLuca Tettamanti } 212ce3cf821SLuca Tettamanti n->enabled = true; 213ce3cf821SLuca Tettamanti n->command_code = params.command_code; 214ce3cf821SLuca Tettamanti } 215ce3cf821SLuca Tettamanti 216ce3cf821SLuca Tettamanti out: 217*fda4b25cSLuca Tettamanti DRM_DEBUG_DRIVER("Notification %s, command code = %#x\n", 218*fda4b25cSLuca Tettamanti (n->enabled ? "enabled" : "disabled"), 219*fda4b25cSLuca Tettamanti n->command_code); 220ce3cf821SLuca Tettamanti kfree(info); 221ce3cf821SLuca Tettamanti return err; 222ce3cf821SLuca Tettamanti } 223ce3cf821SLuca Tettamanti 224*fda4b25cSLuca Tettamanti static int radeon_atif_get_sbios_requests(acpi_handle handle, 225*fda4b25cSLuca Tettamanti struct atif_sbios_requests *req) 226*fda4b25cSLuca Tettamanti { 227*fda4b25cSLuca Tettamanti union acpi_object *info; 228*fda4b25cSLuca Tettamanti size_t size; 229*fda4b25cSLuca Tettamanti int count = 0; 230*fda4b25cSLuca Tettamanti 231*fda4b25cSLuca Tettamanti info = radeon_atif_call(handle, ATIF_FUNCTION_GET_SYSTEM_BIOS_REQUESTS, NULL); 232*fda4b25cSLuca Tettamanti if (!info) 233*fda4b25cSLuca Tettamanti return -EIO; 234*fda4b25cSLuca Tettamanti 235*fda4b25cSLuca Tettamanti size = *(u16 *)info->buffer.pointer; 236*fda4b25cSLuca Tettamanti if (size < 0xd) { 237*fda4b25cSLuca Tettamanti count = -EINVAL; 238*fda4b25cSLuca Tettamanti goto out; 239*fda4b25cSLuca Tettamanti } 240*fda4b25cSLuca Tettamanti memset(req, 0, sizeof(*req)); 241*fda4b25cSLuca Tettamanti 242*fda4b25cSLuca Tettamanti size = min(sizeof(*req), size); 243*fda4b25cSLuca Tettamanti memcpy(req, info->buffer.pointer, size); 244*fda4b25cSLuca Tettamanti DRM_DEBUG_DRIVER("SBIOS pending requests: %#x\n", req->pending); 245*fda4b25cSLuca Tettamanti 246*fda4b25cSLuca Tettamanti count = hweight32(req->pending); 247*fda4b25cSLuca Tettamanti 248*fda4b25cSLuca Tettamanti out: 249*fda4b25cSLuca Tettamanti kfree(info); 250*fda4b25cSLuca Tettamanti return count; 251*fda4b25cSLuca Tettamanti } 252*fda4b25cSLuca Tettamanti 253*fda4b25cSLuca Tettamanti int radeon_atif_handler(struct radeon_device *rdev, 254*fda4b25cSLuca Tettamanti struct acpi_bus_event *event) 255*fda4b25cSLuca Tettamanti { 256*fda4b25cSLuca Tettamanti struct radeon_atif *atif = &rdev->atif; 257*fda4b25cSLuca Tettamanti struct atif_sbios_requests req; 258*fda4b25cSLuca Tettamanti acpi_handle handle; 259*fda4b25cSLuca Tettamanti int count; 260*fda4b25cSLuca Tettamanti 261*fda4b25cSLuca Tettamanti DRM_DEBUG_DRIVER("event, device_class = %s, type = %#x\n", 262*fda4b25cSLuca Tettamanti event->device_class, event->type); 263*fda4b25cSLuca Tettamanti 264*fda4b25cSLuca Tettamanti if (strcmp(event->device_class, ACPI_VIDEO_CLASS) != 0) 265*fda4b25cSLuca Tettamanti return NOTIFY_DONE; 266*fda4b25cSLuca Tettamanti 267*fda4b25cSLuca Tettamanti if (!atif->notification_cfg.enabled || 268*fda4b25cSLuca Tettamanti event->type != atif->notification_cfg.command_code) 269*fda4b25cSLuca Tettamanti /* Not our event */ 270*fda4b25cSLuca Tettamanti return NOTIFY_DONE; 271*fda4b25cSLuca Tettamanti 272*fda4b25cSLuca Tettamanti /* Check pending SBIOS requests */ 273*fda4b25cSLuca Tettamanti handle = DEVICE_ACPI_HANDLE(&rdev->pdev->dev); 274*fda4b25cSLuca Tettamanti count = radeon_atif_get_sbios_requests(handle, &req); 275*fda4b25cSLuca Tettamanti 276*fda4b25cSLuca Tettamanti if (count <= 0) 277*fda4b25cSLuca Tettamanti return NOTIFY_DONE; 278*fda4b25cSLuca Tettamanti 279*fda4b25cSLuca Tettamanti DRM_DEBUG_DRIVER("ATIF: %d pending SBIOS requests\n", count); 280*fda4b25cSLuca Tettamanti 281*fda4b25cSLuca Tettamanti if (req.pending & ATIF_PANEL_BRIGHTNESS_CHANGE_REQUEST) { 282*fda4b25cSLuca Tettamanti struct radeon_encoder *enc = atif->backlight_ctl; 283*fda4b25cSLuca Tettamanti 284*fda4b25cSLuca Tettamanti if (enc) { 285*fda4b25cSLuca Tettamanti struct radeon_encoder_atom_dig *dig = enc->enc_priv; 286*fda4b25cSLuca Tettamanti dig->backlight_level = req.backlight_level; 287*fda4b25cSLuca Tettamanti 288*fda4b25cSLuca Tettamanti DRM_DEBUG_DRIVER("Changing brightness to %d\n", 289*fda4b25cSLuca Tettamanti req.backlight_level); 290*fda4b25cSLuca Tettamanti 291*fda4b25cSLuca Tettamanti atombios_set_panel_brightness(enc); 292*fda4b25cSLuca Tettamanti 293*fda4b25cSLuca Tettamanti backlight_force_update(dig->bl_dev, 294*fda4b25cSLuca Tettamanti BACKLIGHT_UPDATE_HOTKEY); 295*fda4b25cSLuca Tettamanti } 296*fda4b25cSLuca Tettamanti } 297*fda4b25cSLuca Tettamanti /* TODO: check other events */ 298*fda4b25cSLuca Tettamanti 299*fda4b25cSLuca Tettamanti return NOTIFY_OK; 300*fda4b25cSLuca Tettamanti } 301*fda4b25cSLuca Tettamanti 302d7a2952fSAlberto Milone /* Call all ACPI methods here */ 303d7a2952fSAlberto Milone int radeon_acpi_init(struct radeon_device *rdev) 304d7a2952fSAlberto Milone { 305d7a2952fSAlberto Milone acpi_handle handle; 306ce3cf821SLuca Tettamanti struct radeon_atif *atif = &rdev->atif; 307fd64ca8aSLuca Tettamanti int ret; 308d7a2952fSAlberto Milone 309d7a2952fSAlberto Milone /* Get the device handle */ 310d7a2952fSAlberto Milone handle = DEVICE_ACPI_HANDLE(&rdev->pdev->dev); 311d7a2952fSAlberto Milone 31248cc9b2cSJean Delvare /* No need to proceed if we're sure that ATIF is not supported */ 31348cc9b2cSJean Delvare if (!ASIC_IS_AVIVO(rdev) || !rdev->bios || !handle) 31448cc9b2cSJean Delvare return 0; 31548cc9b2cSJean Delvare 316d7a2952fSAlberto Milone /* Call the ATIF method */ 317ce3cf821SLuca Tettamanti ret = radeon_atif_verify_interface(handle, atif); 318ce3cf821SLuca Tettamanti if (ret) { 319fd64ca8aSLuca Tettamanti DRM_DEBUG_DRIVER("Call to verify_interface failed: %d\n", ret); 320ce3cf821SLuca Tettamanti goto out; 321ce3cf821SLuca Tettamanti } 322d7a2952fSAlberto Milone 323*fda4b25cSLuca Tettamanti if (atif->notifications.brightness_change) { 324*fda4b25cSLuca Tettamanti struct drm_encoder *tmp; 325*fda4b25cSLuca Tettamanti struct radeon_encoder *target = NULL; 326*fda4b25cSLuca Tettamanti 327*fda4b25cSLuca Tettamanti /* Find the encoder controlling the brightness */ 328*fda4b25cSLuca Tettamanti list_for_each_entry(tmp, &rdev->ddev->mode_config.encoder_list, 329*fda4b25cSLuca Tettamanti head) { 330*fda4b25cSLuca Tettamanti struct radeon_encoder *enc = to_radeon_encoder(tmp); 331*fda4b25cSLuca Tettamanti struct radeon_encoder_atom_dig *dig = enc->enc_priv; 332*fda4b25cSLuca Tettamanti 333*fda4b25cSLuca Tettamanti if ((enc->devices & (ATOM_DEVICE_LCD_SUPPORT)) && 334*fda4b25cSLuca Tettamanti dig->bl_dev != NULL) { 335*fda4b25cSLuca Tettamanti target = enc; 336*fda4b25cSLuca Tettamanti break; 337*fda4b25cSLuca Tettamanti } 338*fda4b25cSLuca Tettamanti } 339*fda4b25cSLuca Tettamanti 340*fda4b25cSLuca Tettamanti atif->backlight_ctl = target; 341*fda4b25cSLuca Tettamanti if (!target) { 342*fda4b25cSLuca Tettamanti /* Brightness change notification is enabled, but we 343*fda4b25cSLuca Tettamanti * didn't find a backlight controller, this should 344*fda4b25cSLuca Tettamanti * never happen. 345*fda4b25cSLuca Tettamanti */ 346*fda4b25cSLuca Tettamanti DRM_ERROR("Cannot find a backlight controller\n"); 347*fda4b25cSLuca Tettamanti } 348*fda4b25cSLuca Tettamanti } 349*fda4b25cSLuca Tettamanti 350ce3cf821SLuca Tettamanti if (atif->functions.sbios_requests && !atif->functions.system_params) { 351ce3cf821SLuca Tettamanti /* XXX check this workraround, if sbios request function is 352ce3cf821SLuca Tettamanti * present we have to see how it's configured in the system 353ce3cf821SLuca Tettamanti * params 354ce3cf821SLuca Tettamanti */ 355ce3cf821SLuca Tettamanti atif->functions.system_params = true; 356ce3cf821SLuca Tettamanti } 357ce3cf821SLuca Tettamanti 358ce3cf821SLuca Tettamanti if (atif->functions.system_params) { 359ce3cf821SLuca Tettamanti ret = radeon_atif_get_notification_params(handle, 360ce3cf821SLuca Tettamanti &atif->notification_cfg); 361ce3cf821SLuca Tettamanti if (ret) { 362ce3cf821SLuca Tettamanti DRM_DEBUG_DRIVER("Call to GET_SYSTEM_PARAMS failed: %d\n", 363ce3cf821SLuca Tettamanti ret); 364ce3cf821SLuca Tettamanti /* Disable notification */ 365ce3cf821SLuca Tettamanti atif->notification_cfg.enabled = false; 366ce3cf821SLuca Tettamanti } 367ce3cf821SLuca Tettamanti } 368ce3cf821SLuca Tettamanti 369ce3cf821SLuca Tettamanti out: 37086504672SLuca Tettamanti return ret; 371d7a2952fSAlberto Milone } 372d7a2952fSAlberto Milone 373