1*14ca7a47SHans de Goede /* 2*14ca7a47SHans de Goede * video.c - ACPI Video Driver 3*14ca7a47SHans de Goede * 4*14ca7a47SHans de Goede * Copyright (C) 2004 Luming Yu <luming.yu@intel.com> 5*14ca7a47SHans de Goede * Copyright (C) 2004 Bruno Ducrot <ducrot@poupinou.org> 6*14ca7a47SHans de Goede * Copyright (C) 2006 Thomas Tuttle <linux-kernel@ttuttle.net> 7*14ca7a47SHans de Goede * 8*14ca7a47SHans de Goede * ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ 9*14ca7a47SHans de Goede * 10*14ca7a47SHans de Goede * This program is free software; you can redistribute it and/or modify 11*14ca7a47SHans de Goede * it under the terms of the GNU General Public License as published by 12*14ca7a47SHans de Goede * the Free Software Foundation; either version 2 of the License, or (at 13*14ca7a47SHans de Goede * your option) any later version. 14*14ca7a47SHans de Goede * 15*14ca7a47SHans de Goede * This program is distributed in the hope that it will be useful, but 16*14ca7a47SHans de Goede * WITHOUT ANY WARRANTY; without even the implied warranty of 17*14ca7a47SHans de Goede * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU 18*14ca7a47SHans de Goede * General Public License for more details. 19*14ca7a47SHans de Goede * 20*14ca7a47SHans de Goede * You should have received a copy of the GNU General Public License along 21*14ca7a47SHans de Goede * with this program; if not, write to the Free Software Foundation, Inc., 22*14ca7a47SHans de Goede * 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA. 23*14ca7a47SHans de Goede * 24*14ca7a47SHans de Goede * ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ 25*14ca7a47SHans de Goede */ 26*14ca7a47SHans de Goede 27*14ca7a47SHans de Goede #include <linux/kernel.h> 28*14ca7a47SHans de Goede #include <linux/module.h> 29*14ca7a47SHans de Goede #include <linux/init.h> 30*14ca7a47SHans de Goede #include <linux/types.h> 31*14ca7a47SHans de Goede #include <linux/list.h> 32*14ca7a47SHans de Goede #include <linux/mutex.h> 33*14ca7a47SHans de Goede #include <linux/input.h> 34*14ca7a47SHans de Goede #include <linux/backlight.h> 35*14ca7a47SHans de Goede #include <linux/thermal.h> 36*14ca7a47SHans de Goede #include <linux/sort.h> 37*14ca7a47SHans de Goede #include <linux/pci.h> 38*14ca7a47SHans de Goede #include <linux/pci_ids.h> 39*14ca7a47SHans de Goede #include <linux/slab.h> 40*14ca7a47SHans de Goede #include <linux/dmi.h> 41*14ca7a47SHans de Goede #include <linux/suspend.h> 42*14ca7a47SHans de Goede #include <linux/acpi.h> 43*14ca7a47SHans de Goede #include <acpi/video.h> 44*14ca7a47SHans de Goede #include <asm/uaccess.h> 45*14ca7a47SHans de Goede 46*14ca7a47SHans de Goede #define PREFIX "ACPI: " 47*14ca7a47SHans de Goede 48*14ca7a47SHans de Goede #define ACPI_VIDEO_BUS_NAME "Video Bus" 49*14ca7a47SHans de Goede #define ACPI_VIDEO_DEVICE_NAME "Video Device" 50*14ca7a47SHans de Goede #define ACPI_VIDEO_NOTIFY_SWITCH 0x80 51*14ca7a47SHans de Goede #define ACPI_VIDEO_NOTIFY_PROBE 0x81 52*14ca7a47SHans de Goede #define ACPI_VIDEO_NOTIFY_CYCLE 0x82 53*14ca7a47SHans de Goede #define ACPI_VIDEO_NOTIFY_NEXT_OUTPUT 0x83 54*14ca7a47SHans de Goede #define ACPI_VIDEO_NOTIFY_PREV_OUTPUT 0x84 55*14ca7a47SHans de Goede 56*14ca7a47SHans de Goede #define ACPI_VIDEO_NOTIFY_CYCLE_BRIGHTNESS 0x85 57*14ca7a47SHans de Goede #define ACPI_VIDEO_NOTIFY_INC_BRIGHTNESS 0x86 58*14ca7a47SHans de Goede #define ACPI_VIDEO_NOTIFY_DEC_BRIGHTNESS 0x87 59*14ca7a47SHans de Goede #define ACPI_VIDEO_NOTIFY_ZERO_BRIGHTNESS 0x88 60*14ca7a47SHans de Goede #define ACPI_VIDEO_NOTIFY_DISPLAY_OFF 0x89 61*14ca7a47SHans de Goede 62*14ca7a47SHans de Goede #define MAX_NAME_LEN 20 63*14ca7a47SHans de Goede 64*14ca7a47SHans de Goede #define _COMPONENT ACPI_VIDEO_COMPONENT 65*14ca7a47SHans de Goede ACPI_MODULE_NAME("video"); 66*14ca7a47SHans de Goede 67*14ca7a47SHans de Goede MODULE_AUTHOR("Bruno Ducrot"); 68*14ca7a47SHans de Goede MODULE_DESCRIPTION("ACPI Video Driver"); 69*14ca7a47SHans de Goede MODULE_LICENSE("GPL"); 70*14ca7a47SHans de Goede 71*14ca7a47SHans de Goede static bool brightness_switch_enabled = 1; 72*14ca7a47SHans de Goede module_param(brightness_switch_enabled, bool, 0644); 73*14ca7a47SHans de Goede 74*14ca7a47SHans de Goede /* 75*14ca7a47SHans de Goede * By default, we don't allow duplicate ACPI video bus devices 76*14ca7a47SHans de Goede * under the same VGA controller 77*14ca7a47SHans de Goede */ 78*14ca7a47SHans de Goede static bool allow_duplicates; 79*14ca7a47SHans de Goede module_param(allow_duplicates, bool, 0644); 80*14ca7a47SHans de Goede 81*14ca7a47SHans de Goede /* 82*14ca7a47SHans de Goede * For Windows 8 systems: used to decide if video module 83*14ca7a47SHans de Goede * should skip registering backlight interface of its own. 84*14ca7a47SHans de Goede */ 85*14ca7a47SHans de Goede enum { 86*14ca7a47SHans de Goede NATIVE_BACKLIGHT_NOT_SET = -1, 87*14ca7a47SHans de Goede NATIVE_BACKLIGHT_OFF, 88*14ca7a47SHans de Goede NATIVE_BACKLIGHT_ON, 89*14ca7a47SHans de Goede }; 90*14ca7a47SHans de Goede 91*14ca7a47SHans de Goede static int use_native_backlight_param = NATIVE_BACKLIGHT_NOT_SET; 92*14ca7a47SHans de Goede module_param_named(use_native_backlight, use_native_backlight_param, int, 0444); 93*14ca7a47SHans de Goede static int use_native_backlight_dmi = NATIVE_BACKLIGHT_NOT_SET; 94*14ca7a47SHans de Goede 95*14ca7a47SHans de Goede static int disable_backlight_sysfs_if = -1; 96*14ca7a47SHans de Goede module_param(disable_backlight_sysfs_if, int, 0444); 97*14ca7a47SHans de Goede 98*14ca7a47SHans de Goede static int register_count; 99*14ca7a47SHans de Goede static struct mutex video_list_lock; 100*14ca7a47SHans de Goede static struct list_head video_bus_head; 101*14ca7a47SHans de Goede static int acpi_video_bus_add(struct acpi_device *device); 102*14ca7a47SHans de Goede static int acpi_video_bus_remove(struct acpi_device *device); 103*14ca7a47SHans de Goede static void acpi_video_bus_notify(struct acpi_device *device, u32 event); 104*14ca7a47SHans de Goede 105*14ca7a47SHans de Goede static const struct acpi_device_id video_device_ids[] = { 106*14ca7a47SHans de Goede {ACPI_VIDEO_HID, 0}, 107*14ca7a47SHans de Goede {"", 0}, 108*14ca7a47SHans de Goede }; 109*14ca7a47SHans de Goede MODULE_DEVICE_TABLE(acpi, video_device_ids); 110*14ca7a47SHans de Goede 111*14ca7a47SHans de Goede static struct acpi_driver acpi_video_bus = { 112*14ca7a47SHans de Goede .name = "video", 113*14ca7a47SHans de Goede .class = ACPI_VIDEO_CLASS, 114*14ca7a47SHans de Goede .ids = video_device_ids, 115*14ca7a47SHans de Goede .ops = { 116*14ca7a47SHans de Goede .add = acpi_video_bus_add, 117*14ca7a47SHans de Goede .remove = acpi_video_bus_remove, 118*14ca7a47SHans de Goede .notify = acpi_video_bus_notify, 119*14ca7a47SHans de Goede }, 120*14ca7a47SHans de Goede }; 121*14ca7a47SHans de Goede 122*14ca7a47SHans de Goede struct acpi_video_bus_flags { 123*14ca7a47SHans de Goede u8 multihead:1; /* can switch video heads */ 124*14ca7a47SHans de Goede u8 rom:1; /* can retrieve a video rom */ 125*14ca7a47SHans de Goede u8 post:1; /* can configure the head to */ 126*14ca7a47SHans de Goede u8 reserved:5; 127*14ca7a47SHans de Goede }; 128*14ca7a47SHans de Goede 129*14ca7a47SHans de Goede struct acpi_video_bus_cap { 130*14ca7a47SHans de Goede u8 _DOS:1; /* Enable/Disable output switching */ 131*14ca7a47SHans de Goede u8 _DOD:1; /* Enumerate all devices attached to display adapter */ 132*14ca7a47SHans de Goede u8 _ROM:1; /* Get ROM Data */ 133*14ca7a47SHans de Goede u8 _GPD:1; /* Get POST Device */ 134*14ca7a47SHans de Goede u8 _SPD:1; /* Set POST Device */ 135*14ca7a47SHans de Goede u8 _VPO:1; /* Video POST Options */ 136*14ca7a47SHans de Goede u8 reserved:2; 137*14ca7a47SHans de Goede }; 138*14ca7a47SHans de Goede 139*14ca7a47SHans de Goede struct acpi_video_device_attrib { 140*14ca7a47SHans de Goede u32 display_index:4; /* A zero-based instance of the Display */ 141*14ca7a47SHans de Goede u32 display_port_attachment:4; /* This field differentiates the display type */ 142*14ca7a47SHans de Goede u32 display_type:4; /* Describe the specific type in use */ 143*14ca7a47SHans de Goede u32 vendor_specific:4; /* Chipset Vendor Specific */ 144*14ca7a47SHans de Goede u32 bios_can_detect:1; /* BIOS can detect the device */ 145*14ca7a47SHans de Goede u32 depend_on_vga:1; /* Non-VGA output device whose power is related to 146*14ca7a47SHans de Goede the VGA device. */ 147*14ca7a47SHans de Goede u32 pipe_id:3; /* For VGA multiple-head devices. */ 148*14ca7a47SHans de Goede u32 reserved:10; /* Must be 0 */ 149*14ca7a47SHans de Goede u32 device_id_scheme:1; /* Device ID Scheme */ 150*14ca7a47SHans de Goede }; 151*14ca7a47SHans de Goede 152*14ca7a47SHans de Goede struct acpi_video_enumerated_device { 153*14ca7a47SHans de Goede union { 154*14ca7a47SHans de Goede u32 int_val; 155*14ca7a47SHans de Goede struct acpi_video_device_attrib attrib; 156*14ca7a47SHans de Goede } value; 157*14ca7a47SHans de Goede struct acpi_video_device *bind_info; 158*14ca7a47SHans de Goede }; 159*14ca7a47SHans de Goede 160*14ca7a47SHans de Goede struct acpi_video_bus { 161*14ca7a47SHans de Goede struct acpi_device *device; 162*14ca7a47SHans de Goede bool backlight_registered; 163*14ca7a47SHans de Goede bool backlight_notifier_registered; 164*14ca7a47SHans de Goede u8 dos_setting; 165*14ca7a47SHans de Goede struct acpi_video_enumerated_device *attached_array; 166*14ca7a47SHans de Goede u8 attached_count; 167*14ca7a47SHans de Goede u8 child_count; 168*14ca7a47SHans de Goede struct acpi_video_bus_cap cap; 169*14ca7a47SHans de Goede struct acpi_video_bus_flags flags; 170*14ca7a47SHans de Goede struct list_head video_device_list; 171*14ca7a47SHans de Goede struct mutex device_list_lock; /* protects video_device_list */ 172*14ca7a47SHans de Goede struct list_head entry; 173*14ca7a47SHans de Goede struct input_dev *input; 174*14ca7a47SHans de Goede char phys[32]; /* for input device */ 175*14ca7a47SHans de Goede struct notifier_block pm_nb; 176*14ca7a47SHans de Goede struct notifier_block backlight_nb; 177*14ca7a47SHans de Goede }; 178*14ca7a47SHans de Goede 179*14ca7a47SHans de Goede struct acpi_video_device_flags { 180*14ca7a47SHans de Goede u8 crt:1; 181*14ca7a47SHans de Goede u8 lcd:1; 182*14ca7a47SHans de Goede u8 tvout:1; 183*14ca7a47SHans de Goede u8 dvi:1; 184*14ca7a47SHans de Goede u8 bios:1; 185*14ca7a47SHans de Goede u8 unknown:1; 186*14ca7a47SHans de Goede u8 notify:1; 187*14ca7a47SHans de Goede u8 reserved:1; 188*14ca7a47SHans de Goede }; 189*14ca7a47SHans de Goede 190*14ca7a47SHans de Goede struct acpi_video_device_cap { 191*14ca7a47SHans de Goede u8 _ADR:1; /* Return the unique ID */ 192*14ca7a47SHans de Goede u8 _BCL:1; /* Query list of brightness control levels supported */ 193*14ca7a47SHans de Goede u8 _BCM:1; /* Set the brightness level */ 194*14ca7a47SHans de Goede u8 _BQC:1; /* Get current brightness level */ 195*14ca7a47SHans de Goede u8 _BCQ:1; /* Some buggy BIOS uses _BCQ instead of _BQC */ 196*14ca7a47SHans de Goede u8 _DDC:1; /* Return the EDID for this device */ 197*14ca7a47SHans de Goede }; 198*14ca7a47SHans de Goede 199*14ca7a47SHans de Goede struct acpi_video_brightness_flags { 200*14ca7a47SHans de Goede u8 _BCL_no_ac_battery_levels:1; /* no AC/Battery levels in _BCL */ 201*14ca7a47SHans de Goede u8 _BCL_reversed:1; /* _BCL package is in a reversed order */ 202*14ca7a47SHans de Goede u8 _BQC_use_index:1; /* _BQC returns an index value */ 203*14ca7a47SHans de Goede }; 204*14ca7a47SHans de Goede 205*14ca7a47SHans de Goede struct acpi_video_device_brightness { 206*14ca7a47SHans de Goede int curr; 207*14ca7a47SHans de Goede int count; 208*14ca7a47SHans de Goede int *levels; 209*14ca7a47SHans de Goede struct acpi_video_brightness_flags flags; 210*14ca7a47SHans de Goede }; 211*14ca7a47SHans de Goede 212*14ca7a47SHans de Goede struct acpi_video_device { 213*14ca7a47SHans de Goede unsigned long device_id; 214*14ca7a47SHans de Goede struct acpi_video_device_flags flags; 215*14ca7a47SHans de Goede struct acpi_video_device_cap cap; 216*14ca7a47SHans de Goede struct list_head entry; 217*14ca7a47SHans de Goede struct delayed_work switch_brightness_work; 218*14ca7a47SHans de Goede int switch_brightness_event; 219*14ca7a47SHans de Goede struct acpi_video_bus *video; 220*14ca7a47SHans de Goede struct acpi_device *dev; 221*14ca7a47SHans de Goede struct acpi_video_device_brightness *brightness; 222*14ca7a47SHans de Goede struct backlight_device *backlight; 223*14ca7a47SHans de Goede struct thermal_cooling_device *cooling_dev; 224*14ca7a47SHans de Goede }; 225*14ca7a47SHans de Goede 226*14ca7a47SHans de Goede static const char device_decode[][30] = { 227*14ca7a47SHans de Goede "motherboard VGA device", 228*14ca7a47SHans de Goede "PCI VGA device", 229*14ca7a47SHans de Goede "AGP VGA device", 230*14ca7a47SHans de Goede "UNKNOWN", 231*14ca7a47SHans de Goede }; 232*14ca7a47SHans de Goede 233*14ca7a47SHans de Goede static void acpi_video_device_notify(acpi_handle handle, u32 event, void *data); 234*14ca7a47SHans de Goede static void acpi_video_device_rebind(struct acpi_video_bus *video); 235*14ca7a47SHans de Goede static void acpi_video_device_bind(struct acpi_video_bus *video, 236*14ca7a47SHans de Goede struct acpi_video_device *device); 237*14ca7a47SHans de Goede static int acpi_video_device_enumerate(struct acpi_video_bus *video); 238*14ca7a47SHans de Goede static int acpi_video_device_lcd_set_level(struct acpi_video_device *device, 239*14ca7a47SHans de Goede int level); 240*14ca7a47SHans de Goede static int acpi_video_device_lcd_get_level_current( 241*14ca7a47SHans de Goede struct acpi_video_device *device, 242*14ca7a47SHans de Goede unsigned long long *level, bool raw); 243*14ca7a47SHans de Goede static int acpi_video_get_next_level(struct acpi_video_device *device, 244*14ca7a47SHans de Goede u32 level_current, u32 event); 245*14ca7a47SHans de Goede static void acpi_video_switch_brightness(struct work_struct *work); 246*14ca7a47SHans de Goede 247*14ca7a47SHans de Goede static bool acpi_video_use_native_backlight(void) 248*14ca7a47SHans de Goede { 249*14ca7a47SHans de Goede if (use_native_backlight_param != NATIVE_BACKLIGHT_NOT_SET) 250*14ca7a47SHans de Goede return use_native_backlight_param; 251*14ca7a47SHans de Goede else if (use_native_backlight_dmi != NATIVE_BACKLIGHT_NOT_SET) 252*14ca7a47SHans de Goede return use_native_backlight_dmi; 253*14ca7a47SHans de Goede return acpi_osi_is_win8(); 254*14ca7a47SHans de Goede } 255*14ca7a47SHans de Goede 256*14ca7a47SHans de Goede bool acpi_video_verify_backlight_support(void) 257*14ca7a47SHans de Goede { 258*14ca7a47SHans de Goede if (acpi_video_use_native_backlight() && 259*14ca7a47SHans de Goede backlight_device_registered(BACKLIGHT_RAW)) 260*14ca7a47SHans de Goede return false; 261*14ca7a47SHans de Goede return acpi_video_backlight_support(); 262*14ca7a47SHans de Goede } 263*14ca7a47SHans de Goede EXPORT_SYMBOL_GPL(acpi_video_verify_backlight_support); 264*14ca7a47SHans de Goede 265*14ca7a47SHans de Goede /* backlight device sysfs support */ 266*14ca7a47SHans de Goede static int acpi_video_get_brightness(struct backlight_device *bd) 267*14ca7a47SHans de Goede { 268*14ca7a47SHans de Goede unsigned long long cur_level; 269*14ca7a47SHans de Goede int i; 270*14ca7a47SHans de Goede struct acpi_video_device *vd = bl_get_data(bd); 271*14ca7a47SHans de Goede 272*14ca7a47SHans de Goede if (acpi_video_device_lcd_get_level_current(vd, &cur_level, false)) 273*14ca7a47SHans de Goede return -EINVAL; 274*14ca7a47SHans de Goede for (i = 2; i < vd->brightness->count; i++) { 275*14ca7a47SHans de Goede if (vd->brightness->levels[i] == cur_level) 276*14ca7a47SHans de Goede /* 277*14ca7a47SHans de Goede * The first two entries are special - see page 575 278*14ca7a47SHans de Goede * of the ACPI spec 3.0 279*14ca7a47SHans de Goede */ 280*14ca7a47SHans de Goede return i - 2; 281*14ca7a47SHans de Goede } 282*14ca7a47SHans de Goede return 0; 283*14ca7a47SHans de Goede } 284*14ca7a47SHans de Goede 285*14ca7a47SHans de Goede static int acpi_video_set_brightness(struct backlight_device *bd) 286*14ca7a47SHans de Goede { 287*14ca7a47SHans de Goede int request_level = bd->props.brightness + 2; 288*14ca7a47SHans de Goede struct acpi_video_device *vd = bl_get_data(bd); 289*14ca7a47SHans de Goede 290*14ca7a47SHans de Goede cancel_delayed_work(&vd->switch_brightness_work); 291*14ca7a47SHans de Goede return acpi_video_device_lcd_set_level(vd, 292*14ca7a47SHans de Goede vd->brightness->levels[request_level]); 293*14ca7a47SHans de Goede } 294*14ca7a47SHans de Goede 295*14ca7a47SHans de Goede static const struct backlight_ops acpi_backlight_ops = { 296*14ca7a47SHans de Goede .get_brightness = acpi_video_get_brightness, 297*14ca7a47SHans de Goede .update_status = acpi_video_set_brightness, 298*14ca7a47SHans de Goede }; 299*14ca7a47SHans de Goede 300*14ca7a47SHans de Goede /* thermal cooling device callbacks */ 301*14ca7a47SHans de Goede static int video_get_max_state(struct thermal_cooling_device *cooling_dev, unsigned 302*14ca7a47SHans de Goede long *state) 303*14ca7a47SHans de Goede { 304*14ca7a47SHans de Goede struct acpi_device *device = cooling_dev->devdata; 305*14ca7a47SHans de Goede struct acpi_video_device *video = acpi_driver_data(device); 306*14ca7a47SHans de Goede 307*14ca7a47SHans de Goede *state = video->brightness->count - 3; 308*14ca7a47SHans de Goede return 0; 309*14ca7a47SHans de Goede } 310*14ca7a47SHans de Goede 311*14ca7a47SHans de Goede static int video_get_cur_state(struct thermal_cooling_device *cooling_dev, unsigned 312*14ca7a47SHans de Goede long *state) 313*14ca7a47SHans de Goede { 314*14ca7a47SHans de Goede struct acpi_device *device = cooling_dev->devdata; 315*14ca7a47SHans de Goede struct acpi_video_device *video = acpi_driver_data(device); 316*14ca7a47SHans de Goede unsigned long long level; 317*14ca7a47SHans de Goede int offset; 318*14ca7a47SHans de Goede 319*14ca7a47SHans de Goede if (acpi_video_device_lcd_get_level_current(video, &level, false)) 320*14ca7a47SHans de Goede return -EINVAL; 321*14ca7a47SHans de Goede for (offset = 2; offset < video->brightness->count; offset++) 322*14ca7a47SHans de Goede if (level == video->brightness->levels[offset]) { 323*14ca7a47SHans de Goede *state = video->brightness->count - offset - 1; 324*14ca7a47SHans de Goede return 0; 325*14ca7a47SHans de Goede } 326*14ca7a47SHans de Goede 327*14ca7a47SHans de Goede return -EINVAL; 328*14ca7a47SHans de Goede } 329*14ca7a47SHans de Goede 330*14ca7a47SHans de Goede static int 331*14ca7a47SHans de Goede video_set_cur_state(struct thermal_cooling_device *cooling_dev, unsigned long state) 332*14ca7a47SHans de Goede { 333*14ca7a47SHans de Goede struct acpi_device *device = cooling_dev->devdata; 334*14ca7a47SHans de Goede struct acpi_video_device *video = acpi_driver_data(device); 335*14ca7a47SHans de Goede int level; 336*14ca7a47SHans de Goede 337*14ca7a47SHans de Goede if (state >= video->brightness->count - 2) 338*14ca7a47SHans de Goede return -EINVAL; 339*14ca7a47SHans de Goede 340*14ca7a47SHans de Goede state = video->brightness->count - state; 341*14ca7a47SHans de Goede level = video->brightness->levels[state - 1]; 342*14ca7a47SHans de Goede return acpi_video_device_lcd_set_level(video, level); 343*14ca7a47SHans de Goede } 344*14ca7a47SHans de Goede 345*14ca7a47SHans de Goede static const struct thermal_cooling_device_ops video_cooling_ops = { 346*14ca7a47SHans de Goede .get_max_state = video_get_max_state, 347*14ca7a47SHans de Goede .get_cur_state = video_get_cur_state, 348*14ca7a47SHans de Goede .set_cur_state = video_set_cur_state, 349*14ca7a47SHans de Goede }; 350*14ca7a47SHans de Goede 351*14ca7a47SHans de Goede /* 352*14ca7a47SHans de Goede * -------------------------------------------------------------------------- 353*14ca7a47SHans de Goede * Video Management 354*14ca7a47SHans de Goede * -------------------------------------------------------------------------- 355*14ca7a47SHans de Goede */ 356*14ca7a47SHans de Goede 357*14ca7a47SHans de Goede static int 358*14ca7a47SHans de Goede acpi_video_device_lcd_query_levels(struct acpi_video_device *device, 359*14ca7a47SHans de Goede union acpi_object **levels) 360*14ca7a47SHans de Goede { 361*14ca7a47SHans de Goede int status; 362*14ca7a47SHans de Goede struct acpi_buffer buffer = { ACPI_ALLOCATE_BUFFER, NULL }; 363*14ca7a47SHans de Goede union acpi_object *obj; 364*14ca7a47SHans de Goede 365*14ca7a47SHans de Goede 366*14ca7a47SHans de Goede *levels = NULL; 367*14ca7a47SHans de Goede 368*14ca7a47SHans de Goede status = acpi_evaluate_object(device->dev->handle, "_BCL", NULL, &buffer); 369*14ca7a47SHans de Goede if (!ACPI_SUCCESS(status)) 370*14ca7a47SHans de Goede return status; 371*14ca7a47SHans de Goede obj = (union acpi_object *)buffer.pointer; 372*14ca7a47SHans de Goede if (!obj || (obj->type != ACPI_TYPE_PACKAGE)) { 373*14ca7a47SHans de Goede printk(KERN_ERR PREFIX "Invalid _BCL data\n"); 374*14ca7a47SHans de Goede status = -EFAULT; 375*14ca7a47SHans de Goede goto err; 376*14ca7a47SHans de Goede } 377*14ca7a47SHans de Goede 378*14ca7a47SHans de Goede *levels = obj; 379*14ca7a47SHans de Goede 380*14ca7a47SHans de Goede return 0; 381*14ca7a47SHans de Goede 382*14ca7a47SHans de Goede err: 383*14ca7a47SHans de Goede kfree(buffer.pointer); 384*14ca7a47SHans de Goede 385*14ca7a47SHans de Goede return status; 386*14ca7a47SHans de Goede } 387*14ca7a47SHans de Goede 388*14ca7a47SHans de Goede static int 389*14ca7a47SHans de Goede acpi_video_device_lcd_set_level(struct acpi_video_device *device, int level) 390*14ca7a47SHans de Goede { 391*14ca7a47SHans de Goede int status; 392*14ca7a47SHans de Goede int state; 393*14ca7a47SHans de Goede 394*14ca7a47SHans de Goede status = acpi_execute_simple_method(device->dev->handle, 395*14ca7a47SHans de Goede "_BCM", level); 396*14ca7a47SHans de Goede if (ACPI_FAILURE(status)) { 397*14ca7a47SHans de Goede ACPI_ERROR((AE_INFO, "Evaluating _BCM failed")); 398*14ca7a47SHans de Goede return -EIO; 399*14ca7a47SHans de Goede } 400*14ca7a47SHans de Goede 401*14ca7a47SHans de Goede device->brightness->curr = level; 402*14ca7a47SHans de Goede for (state = 2; state < device->brightness->count; state++) 403*14ca7a47SHans de Goede if (level == device->brightness->levels[state]) { 404*14ca7a47SHans de Goede if (device->backlight) 405*14ca7a47SHans de Goede device->backlight->props.brightness = state - 2; 406*14ca7a47SHans de Goede return 0; 407*14ca7a47SHans de Goede } 408*14ca7a47SHans de Goede 409*14ca7a47SHans de Goede ACPI_ERROR((AE_INFO, "Current brightness invalid")); 410*14ca7a47SHans de Goede return -EINVAL; 411*14ca7a47SHans de Goede } 412*14ca7a47SHans de Goede 413*14ca7a47SHans de Goede /* 414*14ca7a47SHans de Goede * For some buggy _BQC methods, we need to add a constant value to 415*14ca7a47SHans de Goede * the _BQC return value to get the actual current brightness level 416*14ca7a47SHans de Goede */ 417*14ca7a47SHans de Goede 418*14ca7a47SHans de Goede static int bqc_offset_aml_bug_workaround; 419*14ca7a47SHans de Goede static int __init video_set_bqc_offset(const struct dmi_system_id *d) 420*14ca7a47SHans de Goede { 421*14ca7a47SHans de Goede bqc_offset_aml_bug_workaround = 9; 422*14ca7a47SHans de Goede return 0; 423*14ca7a47SHans de Goede } 424*14ca7a47SHans de Goede 425*14ca7a47SHans de Goede static int __init video_disable_native_backlight(const struct dmi_system_id *d) 426*14ca7a47SHans de Goede { 427*14ca7a47SHans de Goede use_native_backlight_dmi = NATIVE_BACKLIGHT_OFF; 428*14ca7a47SHans de Goede return 0; 429*14ca7a47SHans de Goede } 430*14ca7a47SHans de Goede 431*14ca7a47SHans de Goede static int __init video_enable_native_backlight(const struct dmi_system_id *d) 432*14ca7a47SHans de Goede { 433*14ca7a47SHans de Goede use_native_backlight_dmi = NATIVE_BACKLIGHT_ON; 434*14ca7a47SHans de Goede return 0; 435*14ca7a47SHans de Goede } 436*14ca7a47SHans de Goede 437*14ca7a47SHans de Goede static int __init video_disable_backlight_sysfs_if( 438*14ca7a47SHans de Goede const struct dmi_system_id *d) 439*14ca7a47SHans de Goede { 440*14ca7a47SHans de Goede if (disable_backlight_sysfs_if == -1) 441*14ca7a47SHans de Goede disable_backlight_sysfs_if = 1; 442*14ca7a47SHans de Goede return 0; 443*14ca7a47SHans de Goede } 444*14ca7a47SHans de Goede 445*14ca7a47SHans de Goede static struct dmi_system_id video_dmi_table[] __initdata = { 446*14ca7a47SHans de Goede /* 447*14ca7a47SHans de Goede * Broken _BQC workaround http://bugzilla.kernel.org/show_bug.cgi?id=13121 448*14ca7a47SHans de Goede */ 449*14ca7a47SHans de Goede { 450*14ca7a47SHans de Goede .callback = video_set_bqc_offset, 451*14ca7a47SHans de Goede .ident = "Acer Aspire 5720", 452*14ca7a47SHans de Goede .matches = { 453*14ca7a47SHans de Goede DMI_MATCH(DMI_BOARD_VENDOR, "Acer"), 454*14ca7a47SHans de Goede DMI_MATCH(DMI_PRODUCT_NAME, "Aspire 5720"), 455*14ca7a47SHans de Goede }, 456*14ca7a47SHans de Goede }, 457*14ca7a47SHans de Goede { 458*14ca7a47SHans de Goede .callback = video_set_bqc_offset, 459*14ca7a47SHans de Goede .ident = "Acer Aspire 5710Z", 460*14ca7a47SHans de Goede .matches = { 461*14ca7a47SHans de Goede DMI_MATCH(DMI_BOARD_VENDOR, "Acer"), 462*14ca7a47SHans de Goede DMI_MATCH(DMI_PRODUCT_NAME, "Aspire 5710Z"), 463*14ca7a47SHans de Goede }, 464*14ca7a47SHans de Goede }, 465*14ca7a47SHans de Goede { 466*14ca7a47SHans de Goede .callback = video_set_bqc_offset, 467*14ca7a47SHans de Goede .ident = "eMachines E510", 468*14ca7a47SHans de Goede .matches = { 469*14ca7a47SHans de Goede DMI_MATCH(DMI_BOARD_VENDOR, "EMACHINES"), 470*14ca7a47SHans de Goede DMI_MATCH(DMI_PRODUCT_NAME, "eMachines E510"), 471*14ca7a47SHans de Goede }, 472*14ca7a47SHans de Goede }, 473*14ca7a47SHans de Goede { 474*14ca7a47SHans de Goede .callback = video_set_bqc_offset, 475*14ca7a47SHans de Goede .ident = "Acer Aspire 5315", 476*14ca7a47SHans de Goede .matches = { 477*14ca7a47SHans de Goede DMI_MATCH(DMI_BOARD_VENDOR, "Acer"), 478*14ca7a47SHans de Goede DMI_MATCH(DMI_PRODUCT_NAME, "Aspire 5315"), 479*14ca7a47SHans de Goede }, 480*14ca7a47SHans de Goede }, 481*14ca7a47SHans de Goede { 482*14ca7a47SHans de Goede .callback = video_set_bqc_offset, 483*14ca7a47SHans de Goede .ident = "Acer Aspire 7720", 484*14ca7a47SHans de Goede .matches = { 485*14ca7a47SHans de Goede DMI_MATCH(DMI_BOARD_VENDOR, "Acer"), 486*14ca7a47SHans de Goede DMI_MATCH(DMI_PRODUCT_NAME, "Aspire 7720"), 487*14ca7a47SHans de Goede }, 488*14ca7a47SHans de Goede }, 489*14ca7a47SHans de Goede 490*14ca7a47SHans de Goede /* 491*14ca7a47SHans de Goede * These models have a working acpi_video backlight control, and using 492*14ca7a47SHans de Goede * native backlight causes a regression where backlight does not work 493*14ca7a47SHans de Goede * when userspace is not handling brightness key events. Disable 494*14ca7a47SHans de Goede * native_backlight on these to fix this: 495*14ca7a47SHans de Goede * https://bugzilla.kernel.org/show_bug.cgi?id=81691 496*14ca7a47SHans de Goede */ 497*14ca7a47SHans de Goede { 498*14ca7a47SHans de Goede .callback = video_disable_native_backlight, 499*14ca7a47SHans de Goede .ident = "ThinkPad T420", 500*14ca7a47SHans de Goede .matches = { 501*14ca7a47SHans de Goede DMI_MATCH(DMI_SYS_VENDOR, "LENOVO"), 502*14ca7a47SHans de Goede DMI_MATCH(DMI_PRODUCT_VERSION, "ThinkPad T420"), 503*14ca7a47SHans de Goede }, 504*14ca7a47SHans de Goede }, 505*14ca7a47SHans de Goede { 506*14ca7a47SHans de Goede .callback = video_disable_native_backlight, 507*14ca7a47SHans de Goede .ident = "ThinkPad T520", 508*14ca7a47SHans de Goede .matches = { 509*14ca7a47SHans de Goede DMI_MATCH(DMI_SYS_VENDOR, "LENOVO"), 510*14ca7a47SHans de Goede DMI_MATCH(DMI_PRODUCT_VERSION, "ThinkPad T520"), 511*14ca7a47SHans de Goede }, 512*14ca7a47SHans de Goede }, 513*14ca7a47SHans de Goede { 514*14ca7a47SHans de Goede .callback = video_disable_native_backlight, 515*14ca7a47SHans de Goede .ident = "ThinkPad X201s", 516*14ca7a47SHans de Goede .matches = { 517*14ca7a47SHans de Goede DMI_MATCH(DMI_SYS_VENDOR, "LENOVO"), 518*14ca7a47SHans de Goede DMI_MATCH(DMI_PRODUCT_VERSION, "ThinkPad X201s"), 519*14ca7a47SHans de Goede }, 520*14ca7a47SHans de Goede }, 521*14ca7a47SHans de Goede 522*14ca7a47SHans de Goede /* The native backlight controls do not work on some older machines */ 523*14ca7a47SHans de Goede { 524*14ca7a47SHans de Goede /* https://bugs.freedesktop.org/show_bug.cgi?id=81515 */ 525*14ca7a47SHans de Goede .callback = video_disable_native_backlight, 526*14ca7a47SHans de Goede .ident = "HP ENVY 15 Notebook", 527*14ca7a47SHans de Goede .matches = { 528*14ca7a47SHans de Goede DMI_MATCH(DMI_SYS_VENDOR, "Hewlett-Packard"), 529*14ca7a47SHans de Goede DMI_MATCH(DMI_PRODUCT_NAME, "HP ENVY 15 Notebook PC"), 530*14ca7a47SHans de Goede }, 531*14ca7a47SHans de Goede }, 532*14ca7a47SHans de Goede 533*14ca7a47SHans de Goede { 534*14ca7a47SHans de Goede .callback = video_disable_native_backlight, 535*14ca7a47SHans de Goede .ident = "SAMSUNG 870Z5E/880Z5E/680Z5E", 536*14ca7a47SHans de Goede .matches = { 537*14ca7a47SHans de Goede DMI_MATCH(DMI_SYS_VENDOR, "SAMSUNG ELECTRONICS CO., LTD."), 538*14ca7a47SHans de Goede DMI_MATCH(DMI_PRODUCT_NAME, "870Z5E/880Z5E/680Z5E"), 539*14ca7a47SHans de Goede }, 540*14ca7a47SHans de Goede }, 541*14ca7a47SHans de Goede { 542*14ca7a47SHans de Goede .callback = video_disable_native_backlight, 543*14ca7a47SHans de Goede .ident = "SAMSUNG 370R4E/370R4V/370R5E/3570RE/370R5V", 544*14ca7a47SHans de Goede .matches = { 545*14ca7a47SHans de Goede DMI_MATCH(DMI_SYS_VENDOR, "SAMSUNG ELECTRONICS CO., LTD."), 546*14ca7a47SHans de Goede DMI_MATCH(DMI_PRODUCT_NAME, "370R4E/370R4V/370R5E/3570RE/370R5V"), 547*14ca7a47SHans de Goede }, 548*14ca7a47SHans de Goede }, 549*14ca7a47SHans de Goede { 550*14ca7a47SHans de Goede /* https://bugzilla.redhat.com/show_bug.cgi?id=1186097 */ 551*14ca7a47SHans de Goede .callback = video_disable_native_backlight, 552*14ca7a47SHans de Goede .ident = "SAMSUNG 3570R/370R/470R/450R/510R/4450RV", 553*14ca7a47SHans de Goede .matches = { 554*14ca7a47SHans de Goede DMI_MATCH(DMI_SYS_VENDOR, "SAMSUNG ELECTRONICS CO., LTD."), 555*14ca7a47SHans de Goede DMI_MATCH(DMI_PRODUCT_NAME, "3570R/370R/470R/450R/510R/4450RV"), 556*14ca7a47SHans de Goede }, 557*14ca7a47SHans de Goede }, 558*14ca7a47SHans de Goede { 559*14ca7a47SHans de Goede /* https://bugzilla.redhat.com/show_bug.cgi?id=1094948 */ 560*14ca7a47SHans de Goede .callback = video_disable_native_backlight, 561*14ca7a47SHans de Goede .ident = "SAMSUNG 730U3E/740U3E", 562*14ca7a47SHans de Goede .matches = { 563*14ca7a47SHans de Goede DMI_MATCH(DMI_SYS_VENDOR, "SAMSUNG ELECTRONICS CO., LTD."), 564*14ca7a47SHans de Goede DMI_MATCH(DMI_PRODUCT_NAME, "730U3E/740U3E"), 565*14ca7a47SHans de Goede }, 566*14ca7a47SHans de Goede }, 567*14ca7a47SHans de Goede { 568*14ca7a47SHans de Goede /* https://bugs.freedesktop.org/show_bug.cgi?id=87286 */ 569*14ca7a47SHans de Goede .callback = video_disable_native_backlight, 570*14ca7a47SHans de Goede .ident = "SAMSUNG 900X3C/900X3D/900X3E/900X4C/900X4D", 571*14ca7a47SHans de Goede .matches = { 572*14ca7a47SHans de Goede DMI_MATCH(DMI_SYS_VENDOR, "SAMSUNG ELECTRONICS CO., LTD."), 573*14ca7a47SHans de Goede DMI_MATCH(DMI_PRODUCT_NAME, "900X3C/900X3D/900X3E/900X4C/900X4D"), 574*14ca7a47SHans de Goede }, 575*14ca7a47SHans de Goede }, 576*14ca7a47SHans de Goede 577*14ca7a47SHans de Goede { 578*14ca7a47SHans de Goede /* https://bugzilla.redhat.com/show_bug.cgi?id=1163574 */ 579*14ca7a47SHans de Goede .callback = video_disable_native_backlight, 580*14ca7a47SHans de Goede .ident = "Dell XPS15 L521X", 581*14ca7a47SHans de Goede .matches = { 582*14ca7a47SHans de Goede DMI_MATCH(DMI_SYS_VENDOR, "Dell Inc."), 583*14ca7a47SHans de Goede DMI_MATCH(DMI_PRODUCT_NAME, "XPS L521X"), 584*14ca7a47SHans de Goede }, 585*14ca7a47SHans de Goede }, 586*14ca7a47SHans de Goede 587*14ca7a47SHans de Goede /* Non win8 machines which need native backlight nevertheless */ 588*14ca7a47SHans de Goede { 589*14ca7a47SHans de Goede /* https://bugzilla.redhat.com/show_bug.cgi?id=1187004 */ 590*14ca7a47SHans de Goede .callback = video_enable_native_backlight, 591*14ca7a47SHans de Goede .ident = "Lenovo Ideapad Z570", 592*14ca7a47SHans de Goede .matches = { 593*14ca7a47SHans de Goede DMI_MATCH(DMI_SYS_VENDOR, "LENOVO"), 594*14ca7a47SHans de Goede DMI_MATCH(DMI_PRODUCT_NAME, "102434U"), 595*14ca7a47SHans de Goede }, 596*14ca7a47SHans de Goede }, 597*14ca7a47SHans de Goede { 598*14ca7a47SHans de Goede /* https://bugzilla.redhat.com/show_bug.cgi?id=1217249 */ 599*14ca7a47SHans de Goede .callback = video_enable_native_backlight, 600*14ca7a47SHans de Goede .ident = "Apple MacBook Pro 12,1", 601*14ca7a47SHans de Goede .matches = { 602*14ca7a47SHans de Goede DMI_MATCH(DMI_SYS_VENDOR, "Apple Inc."), 603*14ca7a47SHans de Goede DMI_MATCH(DMI_PRODUCT_NAME, "MacBookPro12,1"), 604*14ca7a47SHans de Goede }, 605*14ca7a47SHans de Goede }, 606*14ca7a47SHans de Goede 607*14ca7a47SHans de Goede /* 608*14ca7a47SHans de Goede * Some machines have a broken acpi-video interface for brightness 609*14ca7a47SHans de Goede * control, but still need an acpi_video_device_lcd_set_level() call 610*14ca7a47SHans de Goede * on resume to turn the backlight power on. We Enable backlight 611*14ca7a47SHans de Goede * control on these systems, but do not register a backlight sysfs 612*14ca7a47SHans de Goede * as brightness control does not work. 613*14ca7a47SHans de Goede */ 614*14ca7a47SHans de Goede { 615*14ca7a47SHans de Goede /* https://bugs.freedesktop.org/show_bug.cgi?id=82634 */ 616*14ca7a47SHans de Goede .callback = video_disable_backlight_sysfs_if, 617*14ca7a47SHans de Goede .ident = "Toshiba Portege R830", 618*14ca7a47SHans de Goede .matches = { 619*14ca7a47SHans de Goede DMI_MATCH(DMI_SYS_VENDOR, "TOSHIBA"), 620*14ca7a47SHans de Goede DMI_MATCH(DMI_PRODUCT_NAME, "PORTEGE R830"), 621*14ca7a47SHans de Goede }, 622*14ca7a47SHans de Goede }, 623*14ca7a47SHans de Goede {} 624*14ca7a47SHans de Goede }; 625*14ca7a47SHans de Goede 626*14ca7a47SHans de Goede static unsigned long long 627*14ca7a47SHans de Goede acpi_video_bqc_value_to_level(struct acpi_video_device *device, 628*14ca7a47SHans de Goede unsigned long long bqc_value) 629*14ca7a47SHans de Goede { 630*14ca7a47SHans de Goede unsigned long long level; 631*14ca7a47SHans de Goede 632*14ca7a47SHans de Goede if (device->brightness->flags._BQC_use_index) { 633*14ca7a47SHans de Goede /* 634*14ca7a47SHans de Goede * _BQC returns an index that doesn't account for 635*14ca7a47SHans de Goede * the first 2 items with special meaning, so we need 636*14ca7a47SHans de Goede * to compensate for that by offsetting ourselves 637*14ca7a47SHans de Goede */ 638*14ca7a47SHans de Goede if (device->brightness->flags._BCL_reversed) 639*14ca7a47SHans de Goede bqc_value = device->brightness->count - 3 - bqc_value; 640*14ca7a47SHans de Goede 641*14ca7a47SHans de Goede level = device->brightness->levels[bqc_value + 2]; 642*14ca7a47SHans de Goede } else { 643*14ca7a47SHans de Goede level = bqc_value; 644*14ca7a47SHans de Goede } 645*14ca7a47SHans de Goede 646*14ca7a47SHans de Goede level += bqc_offset_aml_bug_workaround; 647*14ca7a47SHans de Goede 648*14ca7a47SHans de Goede return level; 649*14ca7a47SHans de Goede } 650*14ca7a47SHans de Goede 651*14ca7a47SHans de Goede static int 652*14ca7a47SHans de Goede acpi_video_device_lcd_get_level_current(struct acpi_video_device *device, 653*14ca7a47SHans de Goede unsigned long long *level, bool raw) 654*14ca7a47SHans de Goede { 655*14ca7a47SHans de Goede acpi_status status = AE_OK; 656*14ca7a47SHans de Goede int i; 657*14ca7a47SHans de Goede 658*14ca7a47SHans de Goede if (device->cap._BQC || device->cap._BCQ) { 659*14ca7a47SHans de Goede char *buf = device->cap._BQC ? "_BQC" : "_BCQ"; 660*14ca7a47SHans de Goede 661*14ca7a47SHans de Goede status = acpi_evaluate_integer(device->dev->handle, buf, 662*14ca7a47SHans de Goede NULL, level); 663*14ca7a47SHans de Goede if (ACPI_SUCCESS(status)) { 664*14ca7a47SHans de Goede if (raw) { 665*14ca7a47SHans de Goede /* 666*14ca7a47SHans de Goede * Caller has indicated he wants the raw 667*14ca7a47SHans de Goede * value returned by _BQC, so don't furtherly 668*14ca7a47SHans de Goede * mess with the value. 669*14ca7a47SHans de Goede */ 670*14ca7a47SHans de Goede return 0; 671*14ca7a47SHans de Goede } 672*14ca7a47SHans de Goede 673*14ca7a47SHans de Goede *level = acpi_video_bqc_value_to_level(device, *level); 674*14ca7a47SHans de Goede 675*14ca7a47SHans de Goede for (i = 2; i < device->brightness->count; i++) 676*14ca7a47SHans de Goede if (device->brightness->levels[i] == *level) { 677*14ca7a47SHans de Goede device->brightness->curr = *level; 678*14ca7a47SHans de Goede return 0; 679*14ca7a47SHans de Goede } 680*14ca7a47SHans de Goede /* 681*14ca7a47SHans de Goede * BQC returned an invalid level. 682*14ca7a47SHans de Goede * Stop using it. 683*14ca7a47SHans de Goede */ 684*14ca7a47SHans de Goede ACPI_WARNING((AE_INFO, 685*14ca7a47SHans de Goede "%s returned an invalid level", 686*14ca7a47SHans de Goede buf)); 687*14ca7a47SHans de Goede device->cap._BQC = device->cap._BCQ = 0; 688*14ca7a47SHans de Goede } else { 689*14ca7a47SHans de Goede /* 690*14ca7a47SHans de Goede * Fixme: 691*14ca7a47SHans de Goede * should we return an error or ignore this failure? 692*14ca7a47SHans de Goede * dev->brightness->curr is a cached value which stores 693*14ca7a47SHans de Goede * the correct current backlight level in most cases. 694*14ca7a47SHans de Goede * ACPI video backlight still works w/ buggy _BQC. 695*14ca7a47SHans de Goede * http://bugzilla.kernel.org/show_bug.cgi?id=12233 696*14ca7a47SHans de Goede */ 697*14ca7a47SHans de Goede ACPI_WARNING((AE_INFO, "Evaluating %s failed", buf)); 698*14ca7a47SHans de Goede device->cap._BQC = device->cap._BCQ = 0; 699*14ca7a47SHans de Goede } 700*14ca7a47SHans de Goede } 701*14ca7a47SHans de Goede 702*14ca7a47SHans de Goede *level = device->brightness->curr; 703*14ca7a47SHans de Goede return 0; 704*14ca7a47SHans de Goede } 705*14ca7a47SHans de Goede 706*14ca7a47SHans de Goede static int 707*14ca7a47SHans de Goede acpi_video_device_EDID(struct acpi_video_device *device, 708*14ca7a47SHans de Goede union acpi_object **edid, ssize_t length) 709*14ca7a47SHans de Goede { 710*14ca7a47SHans de Goede int status; 711*14ca7a47SHans de Goede struct acpi_buffer buffer = { ACPI_ALLOCATE_BUFFER, NULL }; 712*14ca7a47SHans de Goede union acpi_object *obj; 713*14ca7a47SHans de Goede union acpi_object arg0 = { ACPI_TYPE_INTEGER }; 714*14ca7a47SHans de Goede struct acpi_object_list args = { 1, &arg0 }; 715*14ca7a47SHans de Goede 716*14ca7a47SHans de Goede 717*14ca7a47SHans de Goede *edid = NULL; 718*14ca7a47SHans de Goede 719*14ca7a47SHans de Goede if (!device) 720*14ca7a47SHans de Goede return -ENODEV; 721*14ca7a47SHans de Goede if (length == 128) 722*14ca7a47SHans de Goede arg0.integer.value = 1; 723*14ca7a47SHans de Goede else if (length == 256) 724*14ca7a47SHans de Goede arg0.integer.value = 2; 725*14ca7a47SHans de Goede else 726*14ca7a47SHans de Goede return -EINVAL; 727*14ca7a47SHans de Goede 728*14ca7a47SHans de Goede status = acpi_evaluate_object(device->dev->handle, "_DDC", &args, &buffer); 729*14ca7a47SHans de Goede if (ACPI_FAILURE(status)) 730*14ca7a47SHans de Goede return -ENODEV; 731*14ca7a47SHans de Goede 732*14ca7a47SHans de Goede obj = buffer.pointer; 733*14ca7a47SHans de Goede 734*14ca7a47SHans de Goede if (obj && obj->type == ACPI_TYPE_BUFFER) 735*14ca7a47SHans de Goede *edid = obj; 736*14ca7a47SHans de Goede else { 737*14ca7a47SHans de Goede printk(KERN_ERR PREFIX "Invalid _DDC data\n"); 738*14ca7a47SHans de Goede status = -EFAULT; 739*14ca7a47SHans de Goede kfree(obj); 740*14ca7a47SHans de Goede } 741*14ca7a47SHans de Goede 742*14ca7a47SHans de Goede return status; 743*14ca7a47SHans de Goede } 744*14ca7a47SHans de Goede 745*14ca7a47SHans de Goede /* bus */ 746*14ca7a47SHans de Goede 747*14ca7a47SHans de Goede /* 748*14ca7a47SHans de Goede * Arg: 749*14ca7a47SHans de Goede * video : video bus device pointer 750*14ca7a47SHans de Goede * bios_flag : 751*14ca7a47SHans de Goede * 0. The system BIOS should NOT automatically switch(toggle) 752*14ca7a47SHans de Goede * the active display output. 753*14ca7a47SHans de Goede * 1. The system BIOS should automatically switch (toggle) the 754*14ca7a47SHans de Goede * active display output. No switch event. 755*14ca7a47SHans de Goede * 2. The _DGS value should be locked. 756*14ca7a47SHans de Goede * 3. The system BIOS should not automatically switch (toggle) the 757*14ca7a47SHans de Goede * active display output, but instead generate the display switch 758*14ca7a47SHans de Goede * event notify code. 759*14ca7a47SHans de Goede * lcd_flag : 760*14ca7a47SHans de Goede * 0. The system BIOS should automatically control the brightness level 761*14ca7a47SHans de Goede * of the LCD when the power changes from AC to DC 762*14ca7a47SHans de Goede * 1. The system BIOS should NOT automatically control the brightness 763*14ca7a47SHans de Goede * level of the LCD when the power changes from AC to DC. 764*14ca7a47SHans de Goede * Return Value: 765*14ca7a47SHans de Goede * -EINVAL wrong arg. 766*14ca7a47SHans de Goede */ 767*14ca7a47SHans de Goede 768*14ca7a47SHans de Goede static int 769*14ca7a47SHans de Goede acpi_video_bus_DOS(struct acpi_video_bus *video, int bios_flag, int lcd_flag) 770*14ca7a47SHans de Goede { 771*14ca7a47SHans de Goede acpi_status status; 772*14ca7a47SHans de Goede 773*14ca7a47SHans de Goede if (!video->cap._DOS) 774*14ca7a47SHans de Goede return 0; 775*14ca7a47SHans de Goede 776*14ca7a47SHans de Goede if (bios_flag < 0 || bios_flag > 3 || lcd_flag < 0 || lcd_flag > 1) 777*14ca7a47SHans de Goede return -EINVAL; 778*14ca7a47SHans de Goede video->dos_setting = (lcd_flag << 2) | bios_flag; 779*14ca7a47SHans de Goede status = acpi_execute_simple_method(video->device->handle, "_DOS", 780*14ca7a47SHans de Goede (lcd_flag << 2) | bios_flag); 781*14ca7a47SHans de Goede if (ACPI_FAILURE(status)) 782*14ca7a47SHans de Goede return -EIO; 783*14ca7a47SHans de Goede 784*14ca7a47SHans de Goede return 0; 785*14ca7a47SHans de Goede } 786*14ca7a47SHans de Goede 787*14ca7a47SHans de Goede /* 788*14ca7a47SHans de Goede * Simple comparison function used to sort backlight levels. 789*14ca7a47SHans de Goede */ 790*14ca7a47SHans de Goede 791*14ca7a47SHans de Goede static int 792*14ca7a47SHans de Goede acpi_video_cmp_level(const void *a, const void *b) 793*14ca7a47SHans de Goede { 794*14ca7a47SHans de Goede return *(int *)a - *(int *)b; 795*14ca7a47SHans de Goede } 796*14ca7a47SHans de Goede 797*14ca7a47SHans de Goede /* 798*14ca7a47SHans de Goede * Decides if _BQC/_BCQ for this system is usable 799*14ca7a47SHans de Goede * 800*14ca7a47SHans de Goede * We do this by changing the level first and then read out the current 801*14ca7a47SHans de Goede * brightness level, if the value does not match, find out if it is using 802*14ca7a47SHans de Goede * index. If not, clear the _BQC/_BCQ capability. 803*14ca7a47SHans de Goede */ 804*14ca7a47SHans de Goede static int acpi_video_bqc_quirk(struct acpi_video_device *device, 805*14ca7a47SHans de Goede int max_level, int current_level) 806*14ca7a47SHans de Goede { 807*14ca7a47SHans de Goede struct acpi_video_device_brightness *br = device->brightness; 808*14ca7a47SHans de Goede int result; 809*14ca7a47SHans de Goede unsigned long long level; 810*14ca7a47SHans de Goede int test_level; 811*14ca7a47SHans de Goede 812*14ca7a47SHans de Goede /* don't mess with existing known broken systems */ 813*14ca7a47SHans de Goede if (bqc_offset_aml_bug_workaround) 814*14ca7a47SHans de Goede return 0; 815*14ca7a47SHans de Goede 816*14ca7a47SHans de Goede /* 817*14ca7a47SHans de Goede * Some systems always report current brightness level as maximum 818*14ca7a47SHans de Goede * through _BQC, we need to test another value for them. 819*14ca7a47SHans de Goede */ 820*14ca7a47SHans de Goede test_level = current_level == max_level ? br->levels[3] : max_level; 821*14ca7a47SHans de Goede 822*14ca7a47SHans de Goede result = acpi_video_device_lcd_set_level(device, test_level); 823*14ca7a47SHans de Goede if (result) 824*14ca7a47SHans de Goede return result; 825*14ca7a47SHans de Goede 826*14ca7a47SHans de Goede result = acpi_video_device_lcd_get_level_current(device, &level, true); 827*14ca7a47SHans de Goede if (result) 828*14ca7a47SHans de Goede return result; 829*14ca7a47SHans de Goede 830*14ca7a47SHans de Goede if (level != test_level) { 831*14ca7a47SHans de Goede /* buggy _BQC found, need to find out if it uses index */ 832*14ca7a47SHans de Goede if (level < br->count) { 833*14ca7a47SHans de Goede if (br->flags._BCL_reversed) 834*14ca7a47SHans de Goede level = br->count - 3 - level; 835*14ca7a47SHans de Goede if (br->levels[level + 2] == test_level) 836*14ca7a47SHans de Goede br->flags._BQC_use_index = 1; 837*14ca7a47SHans de Goede } 838*14ca7a47SHans de Goede 839*14ca7a47SHans de Goede if (!br->flags._BQC_use_index) 840*14ca7a47SHans de Goede device->cap._BQC = device->cap._BCQ = 0; 841*14ca7a47SHans de Goede } 842*14ca7a47SHans de Goede 843*14ca7a47SHans de Goede return 0; 844*14ca7a47SHans de Goede } 845*14ca7a47SHans de Goede 846*14ca7a47SHans de Goede 847*14ca7a47SHans de Goede /* 848*14ca7a47SHans de Goede * Arg: 849*14ca7a47SHans de Goede * device : video output device (LCD, CRT, ..) 850*14ca7a47SHans de Goede * 851*14ca7a47SHans de Goede * Return Value: 852*14ca7a47SHans de Goede * Maximum brightness level 853*14ca7a47SHans de Goede * 854*14ca7a47SHans de Goede * Allocate and initialize device->brightness. 855*14ca7a47SHans de Goede */ 856*14ca7a47SHans de Goede 857*14ca7a47SHans de Goede static int 858*14ca7a47SHans de Goede acpi_video_init_brightness(struct acpi_video_device *device) 859*14ca7a47SHans de Goede { 860*14ca7a47SHans de Goede union acpi_object *obj = NULL; 861*14ca7a47SHans de Goede int i, max_level = 0, count = 0, level_ac_battery = 0; 862*14ca7a47SHans de Goede unsigned long long level, level_old; 863*14ca7a47SHans de Goede union acpi_object *o; 864*14ca7a47SHans de Goede struct acpi_video_device_brightness *br = NULL; 865*14ca7a47SHans de Goede int result = -EINVAL; 866*14ca7a47SHans de Goede u32 value; 867*14ca7a47SHans de Goede 868*14ca7a47SHans de Goede if (!ACPI_SUCCESS(acpi_video_device_lcd_query_levels(device, &obj))) { 869*14ca7a47SHans de Goede ACPI_DEBUG_PRINT((ACPI_DB_INFO, "Could not query available " 870*14ca7a47SHans de Goede "LCD brightness level\n")); 871*14ca7a47SHans de Goede goto out; 872*14ca7a47SHans de Goede } 873*14ca7a47SHans de Goede 874*14ca7a47SHans de Goede if (obj->package.count < 2) 875*14ca7a47SHans de Goede goto out; 876*14ca7a47SHans de Goede 877*14ca7a47SHans de Goede br = kzalloc(sizeof(*br), GFP_KERNEL); 878*14ca7a47SHans de Goede if (!br) { 879*14ca7a47SHans de Goede printk(KERN_ERR "can't allocate memory\n"); 880*14ca7a47SHans de Goede result = -ENOMEM; 881*14ca7a47SHans de Goede goto out; 882*14ca7a47SHans de Goede } 883*14ca7a47SHans de Goede 884*14ca7a47SHans de Goede br->levels = kmalloc((obj->package.count + 2) * sizeof *(br->levels), 885*14ca7a47SHans de Goede GFP_KERNEL); 886*14ca7a47SHans de Goede if (!br->levels) { 887*14ca7a47SHans de Goede result = -ENOMEM; 888*14ca7a47SHans de Goede goto out_free; 889*14ca7a47SHans de Goede } 890*14ca7a47SHans de Goede 891*14ca7a47SHans de Goede for (i = 0; i < obj->package.count; i++) { 892*14ca7a47SHans de Goede o = (union acpi_object *)&obj->package.elements[i]; 893*14ca7a47SHans de Goede if (o->type != ACPI_TYPE_INTEGER) { 894*14ca7a47SHans de Goede printk(KERN_ERR PREFIX "Invalid data\n"); 895*14ca7a47SHans de Goede continue; 896*14ca7a47SHans de Goede } 897*14ca7a47SHans de Goede value = (u32) o->integer.value; 898*14ca7a47SHans de Goede /* Skip duplicate entries */ 899*14ca7a47SHans de Goede if (count > 2 && br->levels[count - 1] == value) 900*14ca7a47SHans de Goede continue; 901*14ca7a47SHans de Goede 902*14ca7a47SHans de Goede br->levels[count] = value; 903*14ca7a47SHans de Goede 904*14ca7a47SHans de Goede if (br->levels[count] > max_level) 905*14ca7a47SHans de Goede max_level = br->levels[count]; 906*14ca7a47SHans de Goede count++; 907*14ca7a47SHans de Goede } 908*14ca7a47SHans de Goede 909*14ca7a47SHans de Goede /* 910*14ca7a47SHans de Goede * some buggy BIOS don't export the levels 911*14ca7a47SHans de Goede * when machine is on AC/Battery in _BCL package. 912*14ca7a47SHans de Goede * In this case, the first two elements in _BCL packages 913*14ca7a47SHans de Goede * are also supported brightness levels that OS should take care of. 914*14ca7a47SHans de Goede */ 915*14ca7a47SHans de Goede for (i = 2; i < count; i++) { 916*14ca7a47SHans de Goede if (br->levels[i] == br->levels[0]) 917*14ca7a47SHans de Goede level_ac_battery++; 918*14ca7a47SHans de Goede if (br->levels[i] == br->levels[1]) 919*14ca7a47SHans de Goede level_ac_battery++; 920*14ca7a47SHans de Goede } 921*14ca7a47SHans de Goede 922*14ca7a47SHans de Goede if (level_ac_battery < 2) { 923*14ca7a47SHans de Goede level_ac_battery = 2 - level_ac_battery; 924*14ca7a47SHans de Goede br->flags._BCL_no_ac_battery_levels = 1; 925*14ca7a47SHans de Goede for (i = (count - 1 + level_ac_battery); i >= 2; i--) 926*14ca7a47SHans de Goede br->levels[i] = br->levels[i - level_ac_battery]; 927*14ca7a47SHans de Goede count += level_ac_battery; 928*14ca7a47SHans de Goede } else if (level_ac_battery > 2) 929*14ca7a47SHans de Goede ACPI_ERROR((AE_INFO, "Too many duplicates in _BCL package")); 930*14ca7a47SHans de Goede 931*14ca7a47SHans de Goede /* Check if the _BCL package is in a reversed order */ 932*14ca7a47SHans de Goede if (max_level == br->levels[2]) { 933*14ca7a47SHans de Goede br->flags._BCL_reversed = 1; 934*14ca7a47SHans de Goede sort(&br->levels[2], count - 2, sizeof(br->levels[2]), 935*14ca7a47SHans de Goede acpi_video_cmp_level, NULL); 936*14ca7a47SHans de Goede } else if (max_level != br->levels[count - 1]) 937*14ca7a47SHans de Goede ACPI_ERROR((AE_INFO, 938*14ca7a47SHans de Goede "Found unordered _BCL package")); 939*14ca7a47SHans de Goede 940*14ca7a47SHans de Goede br->count = count; 941*14ca7a47SHans de Goede device->brightness = br; 942*14ca7a47SHans de Goede 943*14ca7a47SHans de Goede /* _BQC uses INDEX while _BCL uses VALUE in some laptops */ 944*14ca7a47SHans de Goede br->curr = level = max_level; 945*14ca7a47SHans de Goede 946*14ca7a47SHans de Goede if (!device->cap._BQC) 947*14ca7a47SHans de Goede goto set_level; 948*14ca7a47SHans de Goede 949*14ca7a47SHans de Goede result = acpi_video_device_lcd_get_level_current(device, 950*14ca7a47SHans de Goede &level_old, true); 951*14ca7a47SHans de Goede if (result) 952*14ca7a47SHans de Goede goto out_free_levels; 953*14ca7a47SHans de Goede 954*14ca7a47SHans de Goede result = acpi_video_bqc_quirk(device, max_level, level_old); 955*14ca7a47SHans de Goede if (result) 956*14ca7a47SHans de Goede goto out_free_levels; 957*14ca7a47SHans de Goede /* 958*14ca7a47SHans de Goede * cap._BQC may get cleared due to _BQC is found to be broken 959*14ca7a47SHans de Goede * in acpi_video_bqc_quirk, so check again here. 960*14ca7a47SHans de Goede */ 961*14ca7a47SHans de Goede if (!device->cap._BQC) 962*14ca7a47SHans de Goede goto set_level; 963*14ca7a47SHans de Goede 964*14ca7a47SHans de Goede level = acpi_video_bqc_value_to_level(device, level_old); 965*14ca7a47SHans de Goede /* 966*14ca7a47SHans de Goede * On some buggy laptops, _BQC returns an uninitialized 967*14ca7a47SHans de Goede * value when invoked for the first time, i.e. 968*14ca7a47SHans de Goede * level_old is invalid (no matter whether it's a level 969*14ca7a47SHans de Goede * or an index). Set the backlight to max_level in this case. 970*14ca7a47SHans de Goede */ 971*14ca7a47SHans de Goede for (i = 2; i < br->count; i++) 972*14ca7a47SHans de Goede if (level == br->levels[i]) 973*14ca7a47SHans de Goede break; 974*14ca7a47SHans de Goede if (i == br->count || !level) 975*14ca7a47SHans de Goede level = max_level; 976*14ca7a47SHans de Goede 977*14ca7a47SHans de Goede set_level: 978*14ca7a47SHans de Goede result = acpi_video_device_lcd_set_level(device, level); 979*14ca7a47SHans de Goede if (result) 980*14ca7a47SHans de Goede goto out_free_levels; 981*14ca7a47SHans de Goede 982*14ca7a47SHans de Goede ACPI_DEBUG_PRINT((ACPI_DB_INFO, 983*14ca7a47SHans de Goede "found %d brightness levels\n", count - 2)); 984*14ca7a47SHans de Goede kfree(obj); 985*14ca7a47SHans de Goede return result; 986*14ca7a47SHans de Goede 987*14ca7a47SHans de Goede out_free_levels: 988*14ca7a47SHans de Goede kfree(br->levels); 989*14ca7a47SHans de Goede out_free: 990*14ca7a47SHans de Goede kfree(br); 991*14ca7a47SHans de Goede out: 992*14ca7a47SHans de Goede device->brightness = NULL; 993*14ca7a47SHans de Goede kfree(obj); 994*14ca7a47SHans de Goede return result; 995*14ca7a47SHans de Goede } 996*14ca7a47SHans de Goede 997*14ca7a47SHans de Goede /* 998*14ca7a47SHans de Goede * Arg: 999*14ca7a47SHans de Goede * device : video output device (LCD, CRT, ..) 1000*14ca7a47SHans de Goede * 1001*14ca7a47SHans de Goede * Return Value: 1002*14ca7a47SHans de Goede * None 1003*14ca7a47SHans de Goede * 1004*14ca7a47SHans de Goede * Find out all required AML methods defined under the output 1005*14ca7a47SHans de Goede * device. 1006*14ca7a47SHans de Goede */ 1007*14ca7a47SHans de Goede 1008*14ca7a47SHans de Goede static void acpi_video_device_find_cap(struct acpi_video_device *device) 1009*14ca7a47SHans de Goede { 1010*14ca7a47SHans de Goede if (acpi_has_method(device->dev->handle, "_ADR")) 1011*14ca7a47SHans de Goede device->cap._ADR = 1; 1012*14ca7a47SHans de Goede if (acpi_has_method(device->dev->handle, "_BCL")) 1013*14ca7a47SHans de Goede device->cap._BCL = 1; 1014*14ca7a47SHans de Goede if (acpi_has_method(device->dev->handle, "_BCM")) 1015*14ca7a47SHans de Goede device->cap._BCM = 1; 1016*14ca7a47SHans de Goede if (acpi_has_method(device->dev->handle, "_BQC")) { 1017*14ca7a47SHans de Goede device->cap._BQC = 1; 1018*14ca7a47SHans de Goede } else if (acpi_has_method(device->dev->handle, "_BCQ")) { 1019*14ca7a47SHans de Goede printk(KERN_WARNING FW_BUG "_BCQ is used instead of _BQC\n"); 1020*14ca7a47SHans de Goede device->cap._BCQ = 1; 1021*14ca7a47SHans de Goede } 1022*14ca7a47SHans de Goede 1023*14ca7a47SHans de Goede if (acpi_has_method(device->dev->handle, "_DDC")) 1024*14ca7a47SHans de Goede device->cap._DDC = 1; 1025*14ca7a47SHans de Goede } 1026*14ca7a47SHans de Goede 1027*14ca7a47SHans de Goede /* 1028*14ca7a47SHans de Goede * Arg: 1029*14ca7a47SHans de Goede * device : video output device (VGA) 1030*14ca7a47SHans de Goede * 1031*14ca7a47SHans de Goede * Return Value: 1032*14ca7a47SHans de Goede * None 1033*14ca7a47SHans de Goede * 1034*14ca7a47SHans de Goede * Find out all required AML methods defined under the video bus device. 1035*14ca7a47SHans de Goede */ 1036*14ca7a47SHans de Goede 1037*14ca7a47SHans de Goede static void acpi_video_bus_find_cap(struct acpi_video_bus *video) 1038*14ca7a47SHans de Goede { 1039*14ca7a47SHans de Goede if (acpi_has_method(video->device->handle, "_DOS")) 1040*14ca7a47SHans de Goede video->cap._DOS = 1; 1041*14ca7a47SHans de Goede if (acpi_has_method(video->device->handle, "_DOD")) 1042*14ca7a47SHans de Goede video->cap._DOD = 1; 1043*14ca7a47SHans de Goede if (acpi_has_method(video->device->handle, "_ROM")) 1044*14ca7a47SHans de Goede video->cap._ROM = 1; 1045*14ca7a47SHans de Goede if (acpi_has_method(video->device->handle, "_GPD")) 1046*14ca7a47SHans de Goede video->cap._GPD = 1; 1047*14ca7a47SHans de Goede if (acpi_has_method(video->device->handle, "_SPD")) 1048*14ca7a47SHans de Goede video->cap._SPD = 1; 1049*14ca7a47SHans de Goede if (acpi_has_method(video->device->handle, "_VPO")) 1050*14ca7a47SHans de Goede video->cap._VPO = 1; 1051*14ca7a47SHans de Goede } 1052*14ca7a47SHans de Goede 1053*14ca7a47SHans de Goede /* 1054*14ca7a47SHans de Goede * Check whether the video bus device has required AML method to 1055*14ca7a47SHans de Goede * support the desired features 1056*14ca7a47SHans de Goede */ 1057*14ca7a47SHans de Goede 1058*14ca7a47SHans de Goede static int acpi_video_bus_check(struct acpi_video_bus *video) 1059*14ca7a47SHans de Goede { 1060*14ca7a47SHans de Goede acpi_status status = -ENOENT; 1061*14ca7a47SHans de Goede struct pci_dev *dev; 1062*14ca7a47SHans de Goede 1063*14ca7a47SHans de Goede if (!video) 1064*14ca7a47SHans de Goede return -EINVAL; 1065*14ca7a47SHans de Goede 1066*14ca7a47SHans de Goede dev = acpi_get_pci_dev(video->device->handle); 1067*14ca7a47SHans de Goede if (!dev) 1068*14ca7a47SHans de Goede return -ENODEV; 1069*14ca7a47SHans de Goede pci_dev_put(dev); 1070*14ca7a47SHans de Goede 1071*14ca7a47SHans de Goede /* 1072*14ca7a47SHans de Goede * Since there is no HID, CID and so on for VGA driver, we have 1073*14ca7a47SHans de Goede * to check well known required nodes. 1074*14ca7a47SHans de Goede */ 1075*14ca7a47SHans de Goede 1076*14ca7a47SHans de Goede /* Does this device support video switching? */ 1077*14ca7a47SHans de Goede if (video->cap._DOS || video->cap._DOD) { 1078*14ca7a47SHans de Goede if (!video->cap._DOS) { 1079*14ca7a47SHans de Goede printk(KERN_WARNING FW_BUG 1080*14ca7a47SHans de Goede "ACPI(%s) defines _DOD but not _DOS\n", 1081*14ca7a47SHans de Goede acpi_device_bid(video->device)); 1082*14ca7a47SHans de Goede } 1083*14ca7a47SHans de Goede video->flags.multihead = 1; 1084*14ca7a47SHans de Goede status = 0; 1085*14ca7a47SHans de Goede } 1086*14ca7a47SHans de Goede 1087*14ca7a47SHans de Goede /* Does this device support retrieving a video ROM? */ 1088*14ca7a47SHans de Goede if (video->cap._ROM) { 1089*14ca7a47SHans de Goede video->flags.rom = 1; 1090*14ca7a47SHans de Goede status = 0; 1091*14ca7a47SHans de Goede } 1092*14ca7a47SHans de Goede 1093*14ca7a47SHans de Goede /* Does this device support configuring which video device to POST? */ 1094*14ca7a47SHans de Goede if (video->cap._GPD && video->cap._SPD && video->cap._VPO) { 1095*14ca7a47SHans de Goede video->flags.post = 1; 1096*14ca7a47SHans de Goede status = 0; 1097*14ca7a47SHans de Goede } 1098*14ca7a47SHans de Goede 1099*14ca7a47SHans de Goede return status; 1100*14ca7a47SHans de Goede } 1101*14ca7a47SHans de Goede 1102*14ca7a47SHans de Goede /* 1103*14ca7a47SHans de Goede * -------------------------------------------------------------------------- 1104*14ca7a47SHans de Goede * Driver Interface 1105*14ca7a47SHans de Goede * -------------------------------------------------------------------------- 1106*14ca7a47SHans de Goede */ 1107*14ca7a47SHans de Goede 1108*14ca7a47SHans de Goede /* device interface */ 1109*14ca7a47SHans de Goede static struct acpi_video_device_attrib * 1110*14ca7a47SHans de Goede acpi_video_get_device_attr(struct acpi_video_bus *video, unsigned long device_id) 1111*14ca7a47SHans de Goede { 1112*14ca7a47SHans de Goede struct acpi_video_enumerated_device *ids; 1113*14ca7a47SHans de Goede int i; 1114*14ca7a47SHans de Goede 1115*14ca7a47SHans de Goede for (i = 0; i < video->attached_count; i++) { 1116*14ca7a47SHans de Goede ids = &video->attached_array[i]; 1117*14ca7a47SHans de Goede if ((ids->value.int_val & 0xffff) == device_id) 1118*14ca7a47SHans de Goede return &ids->value.attrib; 1119*14ca7a47SHans de Goede } 1120*14ca7a47SHans de Goede 1121*14ca7a47SHans de Goede return NULL; 1122*14ca7a47SHans de Goede } 1123*14ca7a47SHans de Goede 1124*14ca7a47SHans de Goede static int 1125*14ca7a47SHans de Goede acpi_video_get_device_type(struct acpi_video_bus *video, 1126*14ca7a47SHans de Goede unsigned long device_id) 1127*14ca7a47SHans de Goede { 1128*14ca7a47SHans de Goede struct acpi_video_enumerated_device *ids; 1129*14ca7a47SHans de Goede int i; 1130*14ca7a47SHans de Goede 1131*14ca7a47SHans de Goede for (i = 0; i < video->attached_count; i++) { 1132*14ca7a47SHans de Goede ids = &video->attached_array[i]; 1133*14ca7a47SHans de Goede if ((ids->value.int_val & 0xffff) == device_id) 1134*14ca7a47SHans de Goede return ids->value.int_val; 1135*14ca7a47SHans de Goede } 1136*14ca7a47SHans de Goede 1137*14ca7a47SHans de Goede return 0; 1138*14ca7a47SHans de Goede } 1139*14ca7a47SHans de Goede 1140*14ca7a47SHans de Goede static int 1141*14ca7a47SHans de Goede acpi_video_bus_get_one_device(struct acpi_device *device, 1142*14ca7a47SHans de Goede struct acpi_video_bus *video) 1143*14ca7a47SHans de Goede { 1144*14ca7a47SHans de Goede unsigned long long device_id; 1145*14ca7a47SHans de Goede int status, device_type; 1146*14ca7a47SHans de Goede struct acpi_video_device *data; 1147*14ca7a47SHans de Goede struct acpi_video_device_attrib *attribute; 1148*14ca7a47SHans de Goede 1149*14ca7a47SHans de Goede status = 1150*14ca7a47SHans de Goede acpi_evaluate_integer(device->handle, "_ADR", NULL, &device_id); 1151*14ca7a47SHans de Goede /* Some device omits _ADR, we skip them instead of fail */ 1152*14ca7a47SHans de Goede if (ACPI_FAILURE(status)) 1153*14ca7a47SHans de Goede return 0; 1154*14ca7a47SHans de Goede 1155*14ca7a47SHans de Goede data = kzalloc(sizeof(struct acpi_video_device), GFP_KERNEL); 1156*14ca7a47SHans de Goede if (!data) 1157*14ca7a47SHans de Goede return -ENOMEM; 1158*14ca7a47SHans de Goede 1159*14ca7a47SHans de Goede strcpy(acpi_device_name(device), ACPI_VIDEO_DEVICE_NAME); 1160*14ca7a47SHans de Goede strcpy(acpi_device_class(device), ACPI_VIDEO_CLASS); 1161*14ca7a47SHans de Goede device->driver_data = data; 1162*14ca7a47SHans de Goede 1163*14ca7a47SHans de Goede data->device_id = device_id; 1164*14ca7a47SHans de Goede data->video = video; 1165*14ca7a47SHans de Goede data->dev = device; 1166*14ca7a47SHans de Goede INIT_DELAYED_WORK(&data->switch_brightness_work, 1167*14ca7a47SHans de Goede acpi_video_switch_brightness); 1168*14ca7a47SHans de Goede 1169*14ca7a47SHans de Goede attribute = acpi_video_get_device_attr(video, device_id); 1170*14ca7a47SHans de Goede 1171*14ca7a47SHans de Goede if (attribute && attribute->device_id_scheme) { 1172*14ca7a47SHans de Goede switch (attribute->display_type) { 1173*14ca7a47SHans de Goede case ACPI_VIDEO_DISPLAY_CRT: 1174*14ca7a47SHans de Goede data->flags.crt = 1; 1175*14ca7a47SHans de Goede break; 1176*14ca7a47SHans de Goede case ACPI_VIDEO_DISPLAY_TV: 1177*14ca7a47SHans de Goede data->flags.tvout = 1; 1178*14ca7a47SHans de Goede break; 1179*14ca7a47SHans de Goede case ACPI_VIDEO_DISPLAY_DVI: 1180*14ca7a47SHans de Goede data->flags.dvi = 1; 1181*14ca7a47SHans de Goede break; 1182*14ca7a47SHans de Goede case ACPI_VIDEO_DISPLAY_LCD: 1183*14ca7a47SHans de Goede data->flags.lcd = 1; 1184*14ca7a47SHans de Goede break; 1185*14ca7a47SHans de Goede default: 1186*14ca7a47SHans de Goede data->flags.unknown = 1; 1187*14ca7a47SHans de Goede break; 1188*14ca7a47SHans de Goede } 1189*14ca7a47SHans de Goede if (attribute->bios_can_detect) 1190*14ca7a47SHans de Goede data->flags.bios = 1; 1191*14ca7a47SHans de Goede } else { 1192*14ca7a47SHans de Goede /* Check for legacy IDs */ 1193*14ca7a47SHans de Goede device_type = acpi_video_get_device_type(video, device_id); 1194*14ca7a47SHans de Goede /* Ignore bits 16 and 18-20 */ 1195*14ca7a47SHans de Goede switch (device_type & 0xffe2ffff) { 1196*14ca7a47SHans de Goede case ACPI_VIDEO_DISPLAY_LEGACY_MONITOR: 1197*14ca7a47SHans de Goede data->flags.crt = 1; 1198*14ca7a47SHans de Goede break; 1199*14ca7a47SHans de Goede case ACPI_VIDEO_DISPLAY_LEGACY_PANEL: 1200*14ca7a47SHans de Goede data->flags.lcd = 1; 1201*14ca7a47SHans de Goede break; 1202*14ca7a47SHans de Goede case ACPI_VIDEO_DISPLAY_LEGACY_TV: 1203*14ca7a47SHans de Goede data->flags.tvout = 1; 1204*14ca7a47SHans de Goede break; 1205*14ca7a47SHans de Goede default: 1206*14ca7a47SHans de Goede data->flags.unknown = 1; 1207*14ca7a47SHans de Goede } 1208*14ca7a47SHans de Goede } 1209*14ca7a47SHans de Goede 1210*14ca7a47SHans de Goede acpi_video_device_bind(video, data); 1211*14ca7a47SHans de Goede acpi_video_device_find_cap(data); 1212*14ca7a47SHans de Goede 1213*14ca7a47SHans de Goede mutex_lock(&video->device_list_lock); 1214*14ca7a47SHans de Goede list_add_tail(&data->entry, &video->video_device_list); 1215*14ca7a47SHans de Goede mutex_unlock(&video->device_list_lock); 1216*14ca7a47SHans de Goede 1217*14ca7a47SHans de Goede return status; 1218*14ca7a47SHans de Goede } 1219*14ca7a47SHans de Goede 1220*14ca7a47SHans de Goede /* 1221*14ca7a47SHans de Goede * Arg: 1222*14ca7a47SHans de Goede * video : video bus device 1223*14ca7a47SHans de Goede * 1224*14ca7a47SHans de Goede * Return: 1225*14ca7a47SHans de Goede * none 1226*14ca7a47SHans de Goede * 1227*14ca7a47SHans de Goede * Enumerate the video device list of the video bus, 1228*14ca7a47SHans de Goede * bind the ids with the corresponding video devices 1229*14ca7a47SHans de Goede * under the video bus. 1230*14ca7a47SHans de Goede */ 1231*14ca7a47SHans de Goede 1232*14ca7a47SHans de Goede static void acpi_video_device_rebind(struct acpi_video_bus *video) 1233*14ca7a47SHans de Goede { 1234*14ca7a47SHans de Goede struct acpi_video_device *dev; 1235*14ca7a47SHans de Goede 1236*14ca7a47SHans de Goede mutex_lock(&video->device_list_lock); 1237*14ca7a47SHans de Goede 1238*14ca7a47SHans de Goede list_for_each_entry(dev, &video->video_device_list, entry) 1239*14ca7a47SHans de Goede acpi_video_device_bind(video, dev); 1240*14ca7a47SHans de Goede 1241*14ca7a47SHans de Goede mutex_unlock(&video->device_list_lock); 1242*14ca7a47SHans de Goede } 1243*14ca7a47SHans de Goede 1244*14ca7a47SHans de Goede /* 1245*14ca7a47SHans de Goede * Arg: 1246*14ca7a47SHans de Goede * video : video bus device 1247*14ca7a47SHans de Goede * device : video output device under the video 1248*14ca7a47SHans de Goede * bus 1249*14ca7a47SHans de Goede * 1250*14ca7a47SHans de Goede * Return: 1251*14ca7a47SHans de Goede * none 1252*14ca7a47SHans de Goede * 1253*14ca7a47SHans de Goede * Bind the ids with the corresponding video devices 1254*14ca7a47SHans de Goede * under the video bus. 1255*14ca7a47SHans de Goede */ 1256*14ca7a47SHans de Goede 1257*14ca7a47SHans de Goede static void 1258*14ca7a47SHans de Goede acpi_video_device_bind(struct acpi_video_bus *video, 1259*14ca7a47SHans de Goede struct acpi_video_device *device) 1260*14ca7a47SHans de Goede { 1261*14ca7a47SHans de Goede struct acpi_video_enumerated_device *ids; 1262*14ca7a47SHans de Goede int i; 1263*14ca7a47SHans de Goede 1264*14ca7a47SHans de Goede for (i = 0; i < video->attached_count; i++) { 1265*14ca7a47SHans de Goede ids = &video->attached_array[i]; 1266*14ca7a47SHans de Goede if (device->device_id == (ids->value.int_val & 0xffff)) { 1267*14ca7a47SHans de Goede ids->bind_info = device; 1268*14ca7a47SHans de Goede ACPI_DEBUG_PRINT((ACPI_DB_INFO, "device_bind %d\n", i)); 1269*14ca7a47SHans de Goede } 1270*14ca7a47SHans de Goede } 1271*14ca7a47SHans de Goede } 1272*14ca7a47SHans de Goede 1273*14ca7a47SHans de Goede static bool acpi_video_device_in_dod(struct acpi_video_device *device) 1274*14ca7a47SHans de Goede { 1275*14ca7a47SHans de Goede struct acpi_video_bus *video = device->video; 1276*14ca7a47SHans de Goede int i; 1277*14ca7a47SHans de Goede 1278*14ca7a47SHans de Goede /* 1279*14ca7a47SHans de Goede * If we have a broken _DOD or we have more than 8 output devices 1280*14ca7a47SHans de Goede * under the graphics controller node that we can't proper deal with 1281*14ca7a47SHans de Goede * in the operation region code currently, no need to test. 1282*14ca7a47SHans de Goede */ 1283*14ca7a47SHans de Goede if (!video->attached_count || video->child_count > 8) 1284*14ca7a47SHans de Goede return true; 1285*14ca7a47SHans de Goede 1286*14ca7a47SHans de Goede for (i = 0; i < video->attached_count; i++) { 1287*14ca7a47SHans de Goede if ((video->attached_array[i].value.int_val & 0xfff) == 1288*14ca7a47SHans de Goede (device->device_id & 0xfff)) 1289*14ca7a47SHans de Goede return true; 1290*14ca7a47SHans de Goede } 1291*14ca7a47SHans de Goede 1292*14ca7a47SHans de Goede return false; 1293*14ca7a47SHans de Goede } 1294*14ca7a47SHans de Goede 1295*14ca7a47SHans de Goede /* 1296*14ca7a47SHans de Goede * Arg: 1297*14ca7a47SHans de Goede * video : video bus device 1298*14ca7a47SHans de Goede * 1299*14ca7a47SHans de Goede * Return: 1300*14ca7a47SHans de Goede * < 0 : error 1301*14ca7a47SHans de Goede * 1302*14ca7a47SHans de Goede * Call _DOD to enumerate all devices attached to display adapter 1303*14ca7a47SHans de Goede * 1304*14ca7a47SHans de Goede */ 1305*14ca7a47SHans de Goede 1306*14ca7a47SHans de Goede static int acpi_video_device_enumerate(struct acpi_video_bus *video) 1307*14ca7a47SHans de Goede { 1308*14ca7a47SHans de Goede int status; 1309*14ca7a47SHans de Goede int count; 1310*14ca7a47SHans de Goede int i; 1311*14ca7a47SHans de Goede struct acpi_video_enumerated_device *active_list; 1312*14ca7a47SHans de Goede struct acpi_buffer buffer = { ACPI_ALLOCATE_BUFFER, NULL }; 1313*14ca7a47SHans de Goede union acpi_object *dod = NULL; 1314*14ca7a47SHans de Goede union acpi_object *obj; 1315*14ca7a47SHans de Goede 1316*14ca7a47SHans de Goede status = acpi_evaluate_object(video->device->handle, "_DOD", NULL, &buffer); 1317*14ca7a47SHans de Goede if (!ACPI_SUCCESS(status)) { 1318*14ca7a47SHans de Goede ACPI_EXCEPTION((AE_INFO, status, "Evaluating _DOD")); 1319*14ca7a47SHans de Goede return status; 1320*14ca7a47SHans de Goede } 1321*14ca7a47SHans de Goede 1322*14ca7a47SHans de Goede dod = buffer.pointer; 1323*14ca7a47SHans de Goede if (!dod || (dod->type != ACPI_TYPE_PACKAGE)) { 1324*14ca7a47SHans de Goede ACPI_EXCEPTION((AE_INFO, status, "Invalid _DOD data")); 1325*14ca7a47SHans de Goede status = -EFAULT; 1326*14ca7a47SHans de Goede goto out; 1327*14ca7a47SHans de Goede } 1328*14ca7a47SHans de Goede 1329*14ca7a47SHans de Goede ACPI_DEBUG_PRINT((ACPI_DB_INFO, "Found %d video heads in _DOD\n", 1330*14ca7a47SHans de Goede dod->package.count)); 1331*14ca7a47SHans de Goede 1332*14ca7a47SHans de Goede active_list = kcalloc(1 + dod->package.count, 1333*14ca7a47SHans de Goede sizeof(struct acpi_video_enumerated_device), 1334*14ca7a47SHans de Goede GFP_KERNEL); 1335*14ca7a47SHans de Goede if (!active_list) { 1336*14ca7a47SHans de Goede status = -ENOMEM; 1337*14ca7a47SHans de Goede goto out; 1338*14ca7a47SHans de Goede } 1339*14ca7a47SHans de Goede 1340*14ca7a47SHans de Goede count = 0; 1341*14ca7a47SHans de Goede for (i = 0; i < dod->package.count; i++) { 1342*14ca7a47SHans de Goede obj = &dod->package.elements[i]; 1343*14ca7a47SHans de Goede 1344*14ca7a47SHans de Goede if (obj->type != ACPI_TYPE_INTEGER) { 1345*14ca7a47SHans de Goede printk(KERN_ERR PREFIX 1346*14ca7a47SHans de Goede "Invalid _DOD data in element %d\n", i); 1347*14ca7a47SHans de Goede continue; 1348*14ca7a47SHans de Goede } 1349*14ca7a47SHans de Goede 1350*14ca7a47SHans de Goede active_list[count].value.int_val = obj->integer.value; 1351*14ca7a47SHans de Goede active_list[count].bind_info = NULL; 1352*14ca7a47SHans de Goede ACPI_DEBUG_PRINT((ACPI_DB_INFO, "dod element[%d] = %d\n", i, 1353*14ca7a47SHans de Goede (int)obj->integer.value)); 1354*14ca7a47SHans de Goede count++; 1355*14ca7a47SHans de Goede } 1356*14ca7a47SHans de Goede 1357*14ca7a47SHans de Goede kfree(video->attached_array); 1358*14ca7a47SHans de Goede 1359*14ca7a47SHans de Goede video->attached_array = active_list; 1360*14ca7a47SHans de Goede video->attached_count = count; 1361*14ca7a47SHans de Goede 1362*14ca7a47SHans de Goede out: 1363*14ca7a47SHans de Goede kfree(buffer.pointer); 1364*14ca7a47SHans de Goede return status; 1365*14ca7a47SHans de Goede } 1366*14ca7a47SHans de Goede 1367*14ca7a47SHans de Goede static int 1368*14ca7a47SHans de Goede acpi_video_get_next_level(struct acpi_video_device *device, 1369*14ca7a47SHans de Goede u32 level_current, u32 event) 1370*14ca7a47SHans de Goede { 1371*14ca7a47SHans de Goede int min, max, min_above, max_below, i, l, delta = 255; 1372*14ca7a47SHans de Goede max = max_below = 0; 1373*14ca7a47SHans de Goede min = min_above = 255; 1374*14ca7a47SHans de Goede /* Find closest level to level_current */ 1375*14ca7a47SHans de Goede for (i = 2; i < device->brightness->count; i++) { 1376*14ca7a47SHans de Goede l = device->brightness->levels[i]; 1377*14ca7a47SHans de Goede if (abs(l - level_current) < abs(delta)) { 1378*14ca7a47SHans de Goede delta = l - level_current; 1379*14ca7a47SHans de Goede if (!delta) 1380*14ca7a47SHans de Goede break; 1381*14ca7a47SHans de Goede } 1382*14ca7a47SHans de Goede } 1383*14ca7a47SHans de Goede /* Ajust level_current to closest available level */ 1384*14ca7a47SHans de Goede level_current += delta; 1385*14ca7a47SHans de Goede for (i = 2; i < device->brightness->count; i++) { 1386*14ca7a47SHans de Goede l = device->brightness->levels[i]; 1387*14ca7a47SHans de Goede if (l < min) 1388*14ca7a47SHans de Goede min = l; 1389*14ca7a47SHans de Goede if (l > max) 1390*14ca7a47SHans de Goede max = l; 1391*14ca7a47SHans de Goede if (l < min_above && l > level_current) 1392*14ca7a47SHans de Goede min_above = l; 1393*14ca7a47SHans de Goede if (l > max_below && l < level_current) 1394*14ca7a47SHans de Goede max_below = l; 1395*14ca7a47SHans de Goede } 1396*14ca7a47SHans de Goede 1397*14ca7a47SHans de Goede switch (event) { 1398*14ca7a47SHans de Goede case ACPI_VIDEO_NOTIFY_CYCLE_BRIGHTNESS: 1399*14ca7a47SHans de Goede return (level_current < max) ? min_above : min; 1400*14ca7a47SHans de Goede case ACPI_VIDEO_NOTIFY_INC_BRIGHTNESS: 1401*14ca7a47SHans de Goede return (level_current < max) ? min_above : max; 1402*14ca7a47SHans de Goede case ACPI_VIDEO_NOTIFY_DEC_BRIGHTNESS: 1403*14ca7a47SHans de Goede return (level_current > min) ? max_below : min; 1404*14ca7a47SHans de Goede case ACPI_VIDEO_NOTIFY_ZERO_BRIGHTNESS: 1405*14ca7a47SHans de Goede case ACPI_VIDEO_NOTIFY_DISPLAY_OFF: 1406*14ca7a47SHans de Goede return 0; 1407*14ca7a47SHans de Goede default: 1408*14ca7a47SHans de Goede return level_current; 1409*14ca7a47SHans de Goede } 1410*14ca7a47SHans de Goede } 1411*14ca7a47SHans de Goede 1412*14ca7a47SHans de Goede static void 1413*14ca7a47SHans de Goede acpi_video_switch_brightness(struct work_struct *work) 1414*14ca7a47SHans de Goede { 1415*14ca7a47SHans de Goede struct acpi_video_device *device = container_of(to_delayed_work(work), 1416*14ca7a47SHans de Goede struct acpi_video_device, switch_brightness_work); 1417*14ca7a47SHans de Goede unsigned long long level_current, level_next; 1418*14ca7a47SHans de Goede int event = device->switch_brightness_event; 1419*14ca7a47SHans de Goede int result = -EINVAL; 1420*14ca7a47SHans de Goede 1421*14ca7a47SHans de Goede /* no warning message if acpi_backlight=vendor or a quirk is used */ 1422*14ca7a47SHans de Goede if (!device->backlight) 1423*14ca7a47SHans de Goede return; 1424*14ca7a47SHans de Goede 1425*14ca7a47SHans de Goede if (!device->brightness) 1426*14ca7a47SHans de Goede goto out; 1427*14ca7a47SHans de Goede 1428*14ca7a47SHans de Goede result = acpi_video_device_lcd_get_level_current(device, 1429*14ca7a47SHans de Goede &level_current, 1430*14ca7a47SHans de Goede false); 1431*14ca7a47SHans de Goede if (result) 1432*14ca7a47SHans de Goede goto out; 1433*14ca7a47SHans de Goede 1434*14ca7a47SHans de Goede level_next = acpi_video_get_next_level(device, level_current, event); 1435*14ca7a47SHans de Goede 1436*14ca7a47SHans de Goede result = acpi_video_device_lcd_set_level(device, level_next); 1437*14ca7a47SHans de Goede 1438*14ca7a47SHans de Goede if (!result) 1439*14ca7a47SHans de Goede backlight_force_update(device->backlight, 1440*14ca7a47SHans de Goede BACKLIGHT_UPDATE_HOTKEY); 1441*14ca7a47SHans de Goede 1442*14ca7a47SHans de Goede out: 1443*14ca7a47SHans de Goede if (result) 1444*14ca7a47SHans de Goede printk(KERN_ERR PREFIX "Failed to switch the brightness\n"); 1445*14ca7a47SHans de Goede } 1446*14ca7a47SHans de Goede 1447*14ca7a47SHans de Goede int acpi_video_get_edid(struct acpi_device *device, int type, int device_id, 1448*14ca7a47SHans de Goede void **edid) 1449*14ca7a47SHans de Goede { 1450*14ca7a47SHans de Goede struct acpi_video_bus *video; 1451*14ca7a47SHans de Goede struct acpi_video_device *video_device; 1452*14ca7a47SHans de Goede union acpi_object *buffer = NULL; 1453*14ca7a47SHans de Goede acpi_status status; 1454*14ca7a47SHans de Goede int i, length; 1455*14ca7a47SHans de Goede 1456*14ca7a47SHans de Goede if (!device || !acpi_driver_data(device)) 1457*14ca7a47SHans de Goede return -EINVAL; 1458*14ca7a47SHans de Goede 1459*14ca7a47SHans de Goede video = acpi_driver_data(device); 1460*14ca7a47SHans de Goede 1461*14ca7a47SHans de Goede for (i = 0; i < video->attached_count; i++) { 1462*14ca7a47SHans de Goede video_device = video->attached_array[i].bind_info; 1463*14ca7a47SHans de Goede length = 256; 1464*14ca7a47SHans de Goede 1465*14ca7a47SHans de Goede if (!video_device) 1466*14ca7a47SHans de Goede continue; 1467*14ca7a47SHans de Goede 1468*14ca7a47SHans de Goede if (!video_device->cap._DDC) 1469*14ca7a47SHans de Goede continue; 1470*14ca7a47SHans de Goede 1471*14ca7a47SHans de Goede if (type) { 1472*14ca7a47SHans de Goede switch (type) { 1473*14ca7a47SHans de Goede case ACPI_VIDEO_DISPLAY_CRT: 1474*14ca7a47SHans de Goede if (!video_device->flags.crt) 1475*14ca7a47SHans de Goede continue; 1476*14ca7a47SHans de Goede break; 1477*14ca7a47SHans de Goede case ACPI_VIDEO_DISPLAY_TV: 1478*14ca7a47SHans de Goede if (!video_device->flags.tvout) 1479*14ca7a47SHans de Goede continue; 1480*14ca7a47SHans de Goede break; 1481*14ca7a47SHans de Goede case ACPI_VIDEO_DISPLAY_DVI: 1482*14ca7a47SHans de Goede if (!video_device->flags.dvi) 1483*14ca7a47SHans de Goede continue; 1484*14ca7a47SHans de Goede break; 1485*14ca7a47SHans de Goede case ACPI_VIDEO_DISPLAY_LCD: 1486*14ca7a47SHans de Goede if (!video_device->flags.lcd) 1487*14ca7a47SHans de Goede continue; 1488*14ca7a47SHans de Goede break; 1489*14ca7a47SHans de Goede } 1490*14ca7a47SHans de Goede } else if (video_device->device_id != device_id) { 1491*14ca7a47SHans de Goede continue; 1492*14ca7a47SHans de Goede } 1493*14ca7a47SHans de Goede 1494*14ca7a47SHans de Goede status = acpi_video_device_EDID(video_device, &buffer, length); 1495*14ca7a47SHans de Goede 1496*14ca7a47SHans de Goede if (ACPI_FAILURE(status) || !buffer || 1497*14ca7a47SHans de Goede buffer->type != ACPI_TYPE_BUFFER) { 1498*14ca7a47SHans de Goede length = 128; 1499*14ca7a47SHans de Goede status = acpi_video_device_EDID(video_device, &buffer, 1500*14ca7a47SHans de Goede length); 1501*14ca7a47SHans de Goede if (ACPI_FAILURE(status) || !buffer || 1502*14ca7a47SHans de Goede buffer->type != ACPI_TYPE_BUFFER) { 1503*14ca7a47SHans de Goede continue; 1504*14ca7a47SHans de Goede } 1505*14ca7a47SHans de Goede } 1506*14ca7a47SHans de Goede 1507*14ca7a47SHans de Goede *edid = buffer->buffer.pointer; 1508*14ca7a47SHans de Goede return length; 1509*14ca7a47SHans de Goede } 1510*14ca7a47SHans de Goede 1511*14ca7a47SHans de Goede return -ENODEV; 1512*14ca7a47SHans de Goede } 1513*14ca7a47SHans de Goede EXPORT_SYMBOL(acpi_video_get_edid); 1514*14ca7a47SHans de Goede 1515*14ca7a47SHans de Goede static int 1516*14ca7a47SHans de Goede acpi_video_bus_get_devices(struct acpi_video_bus *video, 1517*14ca7a47SHans de Goede struct acpi_device *device) 1518*14ca7a47SHans de Goede { 1519*14ca7a47SHans de Goede int status = 0; 1520*14ca7a47SHans de Goede struct acpi_device *dev; 1521*14ca7a47SHans de Goede 1522*14ca7a47SHans de Goede /* 1523*14ca7a47SHans de Goede * There are systems where video module known to work fine regardless 1524*14ca7a47SHans de Goede * of broken _DOD and ignoring returned value here doesn't cause 1525*14ca7a47SHans de Goede * any issues later. 1526*14ca7a47SHans de Goede */ 1527*14ca7a47SHans de Goede acpi_video_device_enumerate(video); 1528*14ca7a47SHans de Goede 1529*14ca7a47SHans de Goede list_for_each_entry(dev, &device->children, node) { 1530*14ca7a47SHans de Goede 1531*14ca7a47SHans de Goede status = acpi_video_bus_get_one_device(dev, video); 1532*14ca7a47SHans de Goede if (status) { 1533*14ca7a47SHans de Goede dev_err(&dev->dev, "Can't attach device\n"); 1534*14ca7a47SHans de Goede break; 1535*14ca7a47SHans de Goede } 1536*14ca7a47SHans de Goede video->child_count++; 1537*14ca7a47SHans de Goede } 1538*14ca7a47SHans de Goede return status; 1539*14ca7a47SHans de Goede } 1540*14ca7a47SHans de Goede 1541*14ca7a47SHans de Goede /* acpi_video interface */ 1542*14ca7a47SHans de Goede 1543*14ca7a47SHans de Goede /* 1544*14ca7a47SHans de Goede * Win8 requires setting bit2 of _DOS to let firmware know it shouldn't 1545*14ca7a47SHans de Goede * preform any automatic brightness change on receiving a notification. 1546*14ca7a47SHans de Goede */ 1547*14ca7a47SHans de Goede static int acpi_video_bus_start_devices(struct acpi_video_bus *video) 1548*14ca7a47SHans de Goede { 1549*14ca7a47SHans de Goede return acpi_video_bus_DOS(video, 0, 1550*14ca7a47SHans de Goede acpi_osi_is_win8() ? 1 : 0); 1551*14ca7a47SHans de Goede } 1552*14ca7a47SHans de Goede 1553*14ca7a47SHans de Goede static int acpi_video_bus_stop_devices(struct acpi_video_bus *video) 1554*14ca7a47SHans de Goede { 1555*14ca7a47SHans de Goede return acpi_video_bus_DOS(video, 0, 1556*14ca7a47SHans de Goede acpi_osi_is_win8() ? 0 : 1); 1557*14ca7a47SHans de Goede } 1558*14ca7a47SHans de Goede 1559*14ca7a47SHans de Goede static void acpi_video_bus_notify(struct acpi_device *device, u32 event) 1560*14ca7a47SHans de Goede { 1561*14ca7a47SHans de Goede struct acpi_video_bus *video = acpi_driver_data(device); 1562*14ca7a47SHans de Goede struct input_dev *input; 1563*14ca7a47SHans de Goede int keycode = 0; 1564*14ca7a47SHans de Goede 1565*14ca7a47SHans de Goede if (!video || !video->input) 1566*14ca7a47SHans de Goede return; 1567*14ca7a47SHans de Goede 1568*14ca7a47SHans de Goede input = video->input; 1569*14ca7a47SHans de Goede 1570*14ca7a47SHans de Goede switch (event) { 1571*14ca7a47SHans de Goede case ACPI_VIDEO_NOTIFY_SWITCH: /* User requested a switch, 1572*14ca7a47SHans de Goede * most likely via hotkey. */ 1573*14ca7a47SHans de Goede keycode = KEY_SWITCHVIDEOMODE; 1574*14ca7a47SHans de Goede break; 1575*14ca7a47SHans de Goede 1576*14ca7a47SHans de Goede case ACPI_VIDEO_NOTIFY_PROBE: /* User plugged in or removed a video 1577*14ca7a47SHans de Goede * connector. */ 1578*14ca7a47SHans de Goede acpi_video_device_enumerate(video); 1579*14ca7a47SHans de Goede acpi_video_device_rebind(video); 1580*14ca7a47SHans de Goede keycode = KEY_SWITCHVIDEOMODE; 1581*14ca7a47SHans de Goede break; 1582*14ca7a47SHans de Goede 1583*14ca7a47SHans de Goede case ACPI_VIDEO_NOTIFY_CYCLE: /* Cycle Display output hotkey pressed. */ 1584*14ca7a47SHans de Goede keycode = KEY_SWITCHVIDEOMODE; 1585*14ca7a47SHans de Goede break; 1586*14ca7a47SHans de Goede case ACPI_VIDEO_NOTIFY_NEXT_OUTPUT: /* Next Display output hotkey pressed. */ 1587*14ca7a47SHans de Goede keycode = KEY_VIDEO_NEXT; 1588*14ca7a47SHans de Goede break; 1589*14ca7a47SHans de Goede case ACPI_VIDEO_NOTIFY_PREV_OUTPUT: /* previous Display output hotkey pressed. */ 1590*14ca7a47SHans de Goede keycode = KEY_VIDEO_PREV; 1591*14ca7a47SHans de Goede break; 1592*14ca7a47SHans de Goede 1593*14ca7a47SHans de Goede default: 1594*14ca7a47SHans de Goede ACPI_DEBUG_PRINT((ACPI_DB_INFO, 1595*14ca7a47SHans de Goede "Unsupported event [0x%x]\n", event)); 1596*14ca7a47SHans de Goede break; 1597*14ca7a47SHans de Goede } 1598*14ca7a47SHans de Goede 1599*14ca7a47SHans de Goede if (acpi_notifier_call_chain(device, event, 0)) 1600*14ca7a47SHans de Goede /* Something vetoed the keypress. */ 1601*14ca7a47SHans de Goede keycode = 0; 1602*14ca7a47SHans de Goede 1603*14ca7a47SHans de Goede if (keycode) { 1604*14ca7a47SHans de Goede input_report_key(input, keycode, 1); 1605*14ca7a47SHans de Goede input_sync(input); 1606*14ca7a47SHans de Goede input_report_key(input, keycode, 0); 1607*14ca7a47SHans de Goede input_sync(input); 1608*14ca7a47SHans de Goede } 1609*14ca7a47SHans de Goede 1610*14ca7a47SHans de Goede return; 1611*14ca7a47SHans de Goede } 1612*14ca7a47SHans de Goede 1613*14ca7a47SHans de Goede static void brightness_switch_event(struct acpi_video_device *video_device, 1614*14ca7a47SHans de Goede u32 event) 1615*14ca7a47SHans de Goede { 1616*14ca7a47SHans de Goede if (!brightness_switch_enabled) 1617*14ca7a47SHans de Goede return; 1618*14ca7a47SHans de Goede 1619*14ca7a47SHans de Goede video_device->switch_brightness_event = event; 1620*14ca7a47SHans de Goede schedule_delayed_work(&video_device->switch_brightness_work, HZ / 10); 1621*14ca7a47SHans de Goede } 1622*14ca7a47SHans de Goede 1623*14ca7a47SHans de Goede static void acpi_video_device_notify(acpi_handle handle, u32 event, void *data) 1624*14ca7a47SHans de Goede { 1625*14ca7a47SHans de Goede struct acpi_video_device *video_device = data; 1626*14ca7a47SHans de Goede struct acpi_device *device = NULL; 1627*14ca7a47SHans de Goede struct acpi_video_bus *bus; 1628*14ca7a47SHans de Goede struct input_dev *input; 1629*14ca7a47SHans de Goede int keycode = 0; 1630*14ca7a47SHans de Goede 1631*14ca7a47SHans de Goede if (!video_device) 1632*14ca7a47SHans de Goede return; 1633*14ca7a47SHans de Goede 1634*14ca7a47SHans de Goede device = video_device->dev; 1635*14ca7a47SHans de Goede bus = video_device->video; 1636*14ca7a47SHans de Goede input = bus->input; 1637*14ca7a47SHans de Goede 1638*14ca7a47SHans de Goede switch (event) { 1639*14ca7a47SHans de Goede case ACPI_VIDEO_NOTIFY_CYCLE_BRIGHTNESS: /* Cycle brightness */ 1640*14ca7a47SHans de Goede brightness_switch_event(video_device, event); 1641*14ca7a47SHans de Goede keycode = KEY_BRIGHTNESS_CYCLE; 1642*14ca7a47SHans de Goede break; 1643*14ca7a47SHans de Goede case ACPI_VIDEO_NOTIFY_INC_BRIGHTNESS: /* Increase brightness */ 1644*14ca7a47SHans de Goede brightness_switch_event(video_device, event); 1645*14ca7a47SHans de Goede keycode = KEY_BRIGHTNESSUP; 1646*14ca7a47SHans de Goede break; 1647*14ca7a47SHans de Goede case ACPI_VIDEO_NOTIFY_DEC_BRIGHTNESS: /* Decrease brightness */ 1648*14ca7a47SHans de Goede brightness_switch_event(video_device, event); 1649*14ca7a47SHans de Goede keycode = KEY_BRIGHTNESSDOWN; 1650*14ca7a47SHans de Goede break; 1651*14ca7a47SHans de Goede case ACPI_VIDEO_NOTIFY_ZERO_BRIGHTNESS: /* zero brightness */ 1652*14ca7a47SHans de Goede brightness_switch_event(video_device, event); 1653*14ca7a47SHans de Goede keycode = KEY_BRIGHTNESS_ZERO; 1654*14ca7a47SHans de Goede break; 1655*14ca7a47SHans de Goede case ACPI_VIDEO_NOTIFY_DISPLAY_OFF: /* display device off */ 1656*14ca7a47SHans de Goede brightness_switch_event(video_device, event); 1657*14ca7a47SHans de Goede keycode = KEY_DISPLAY_OFF; 1658*14ca7a47SHans de Goede break; 1659*14ca7a47SHans de Goede default: 1660*14ca7a47SHans de Goede ACPI_DEBUG_PRINT((ACPI_DB_INFO, 1661*14ca7a47SHans de Goede "Unsupported event [0x%x]\n", event)); 1662*14ca7a47SHans de Goede break; 1663*14ca7a47SHans de Goede } 1664*14ca7a47SHans de Goede 1665*14ca7a47SHans de Goede acpi_notifier_call_chain(device, event, 0); 1666*14ca7a47SHans de Goede 1667*14ca7a47SHans de Goede if (keycode) { 1668*14ca7a47SHans de Goede input_report_key(input, keycode, 1); 1669*14ca7a47SHans de Goede input_sync(input); 1670*14ca7a47SHans de Goede input_report_key(input, keycode, 0); 1671*14ca7a47SHans de Goede input_sync(input); 1672*14ca7a47SHans de Goede } 1673*14ca7a47SHans de Goede 1674*14ca7a47SHans de Goede return; 1675*14ca7a47SHans de Goede } 1676*14ca7a47SHans de Goede 1677*14ca7a47SHans de Goede static int acpi_video_resume(struct notifier_block *nb, 1678*14ca7a47SHans de Goede unsigned long val, void *ign) 1679*14ca7a47SHans de Goede { 1680*14ca7a47SHans de Goede struct acpi_video_bus *video; 1681*14ca7a47SHans de Goede struct acpi_video_device *video_device; 1682*14ca7a47SHans de Goede int i; 1683*14ca7a47SHans de Goede 1684*14ca7a47SHans de Goede switch (val) { 1685*14ca7a47SHans de Goede case PM_HIBERNATION_PREPARE: 1686*14ca7a47SHans de Goede case PM_SUSPEND_PREPARE: 1687*14ca7a47SHans de Goede case PM_RESTORE_PREPARE: 1688*14ca7a47SHans de Goede return NOTIFY_DONE; 1689*14ca7a47SHans de Goede } 1690*14ca7a47SHans de Goede 1691*14ca7a47SHans de Goede video = container_of(nb, struct acpi_video_bus, pm_nb); 1692*14ca7a47SHans de Goede 1693*14ca7a47SHans de Goede dev_info(&video->device->dev, "Restoring backlight state\n"); 1694*14ca7a47SHans de Goede 1695*14ca7a47SHans de Goede for (i = 0; i < video->attached_count; i++) { 1696*14ca7a47SHans de Goede video_device = video->attached_array[i].bind_info; 1697*14ca7a47SHans de Goede if (video_device && video_device->brightness) 1698*14ca7a47SHans de Goede acpi_video_device_lcd_set_level(video_device, 1699*14ca7a47SHans de Goede video_device->brightness->curr); 1700*14ca7a47SHans de Goede } 1701*14ca7a47SHans de Goede 1702*14ca7a47SHans de Goede return NOTIFY_OK; 1703*14ca7a47SHans de Goede } 1704*14ca7a47SHans de Goede 1705*14ca7a47SHans de Goede static acpi_status 1706*14ca7a47SHans de Goede acpi_video_bus_match(acpi_handle handle, u32 level, void *context, 1707*14ca7a47SHans de Goede void **return_value) 1708*14ca7a47SHans de Goede { 1709*14ca7a47SHans de Goede struct acpi_device *device = context; 1710*14ca7a47SHans de Goede struct acpi_device *sibling; 1711*14ca7a47SHans de Goede int result; 1712*14ca7a47SHans de Goede 1713*14ca7a47SHans de Goede if (handle == device->handle) 1714*14ca7a47SHans de Goede return AE_CTRL_TERMINATE; 1715*14ca7a47SHans de Goede 1716*14ca7a47SHans de Goede result = acpi_bus_get_device(handle, &sibling); 1717*14ca7a47SHans de Goede if (result) 1718*14ca7a47SHans de Goede return AE_OK; 1719*14ca7a47SHans de Goede 1720*14ca7a47SHans de Goede if (!strcmp(acpi_device_name(sibling), ACPI_VIDEO_BUS_NAME)) 1721*14ca7a47SHans de Goede return AE_ALREADY_EXISTS; 1722*14ca7a47SHans de Goede 1723*14ca7a47SHans de Goede return AE_OK; 1724*14ca7a47SHans de Goede } 1725*14ca7a47SHans de Goede 1726*14ca7a47SHans de Goede static void acpi_video_dev_register_backlight(struct acpi_video_device *device) 1727*14ca7a47SHans de Goede { 1728*14ca7a47SHans de Goede struct backlight_properties props; 1729*14ca7a47SHans de Goede struct pci_dev *pdev; 1730*14ca7a47SHans de Goede acpi_handle acpi_parent; 1731*14ca7a47SHans de Goede struct device *parent = NULL; 1732*14ca7a47SHans de Goede int result; 1733*14ca7a47SHans de Goede static int count; 1734*14ca7a47SHans de Goede char *name; 1735*14ca7a47SHans de Goede 1736*14ca7a47SHans de Goede /* 1737*14ca7a47SHans de Goede * Do not create backlight device for video output 1738*14ca7a47SHans de Goede * device that is not in the enumerated list. 1739*14ca7a47SHans de Goede */ 1740*14ca7a47SHans de Goede if (!acpi_video_device_in_dod(device)) { 1741*14ca7a47SHans de Goede dev_dbg(&device->dev->dev, "not in _DOD list, ignore\n"); 1742*14ca7a47SHans de Goede return; 1743*14ca7a47SHans de Goede } 1744*14ca7a47SHans de Goede 1745*14ca7a47SHans de Goede result = acpi_video_init_brightness(device); 1746*14ca7a47SHans de Goede if (result) 1747*14ca7a47SHans de Goede return; 1748*14ca7a47SHans de Goede 1749*14ca7a47SHans de Goede if (disable_backlight_sysfs_if > 0) 1750*14ca7a47SHans de Goede return; 1751*14ca7a47SHans de Goede 1752*14ca7a47SHans de Goede name = kasprintf(GFP_KERNEL, "acpi_video%d", count); 1753*14ca7a47SHans de Goede if (!name) 1754*14ca7a47SHans de Goede return; 1755*14ca7a47SHans de Goede count++; 1756*14ca7a47SHans de Goede 1757*14ca7a47SHans de Goede acpi_get_parent(device->dev->handle, &acpi_parent); 1758*14ca7a47SHans de Goede 1759*14ca7a47SHans de Goede pdev = acpi_get_pci_dev(acpi_parent); 1760*14ca7a47SHans de Goede if (pdev) { 1761*14ca7a47SHans de Goede parent = &pdev->dev; 1762*14ca7a47SHans de Goede pci_dev_put(pdev); 1763*14ca7a47SHans de Goede } 1764*14ca7a47SHans de Goede 1765*14ca7a47SHans de Goede memset(&props, 0, sizeof(struct backlight_properties)); 1766*14ca7a47SHans de Goede props.type = BACKLIGHT_FIRMWARE; 1767*14ca7a47SHans de Goede props.max_brightness = device->brightness->count - 3; 1768*14ca7a47SHans de Goede device->backlight = backlight_device_register(name, 1769*14ca7a47SHans de Goede parent, 1770*14ca7a47SHans de Goede device, 1771*14ca7a47SHans de Goede &acpi_backlight_ops, 1772*14ca7a47SHans de Goede &props); 1773*14ca7a47SHans de Goede kfree(name); 1774*14ca7a47SHans de Goede if (IS_ERR(device->backlight)) { 1775*14ca7a47SHans de Goede device->backlight = NULL; 1776*14ca7a47SHans de Goede return; 1777*14ca7a47SHans de Goede } 1778*14ca7a47SHans de Goede 1779*14ca7a47SHans de Goede /* 1780*14ca7a47SHans de Goede * Save current brightness level in case we have to restore it 1781*14ca7a47SHans de Goede * before acpi_video_device_lcd_set_level() is called next time. 1782*14ca7a47SHans de Goede */ 1783*14ca7a47SHans de Goede device->backlight->props.brightness = 1784*14ca7a47SHans de Goede acpi_video_get_brightness(device->backlight); 1785*14ca7a47SHans de Goede 1786*14ca7a47SHans de Goede device->cooling_dev = thermal_cooling_device_register("LCD", 1787*14ca7a47SHans de Goede device->dev, &video_cooling_ops); 1788*14ca7a47SHans de Goede if (IS_ERR(device->cooling_dev)) { 1789*14ca7a47SHans de Goede /* 1790*14ca7a47SHans de Goede * Set cooling_dev to NULL so we don't crash trying to free it. 1791*14ca7a47SHans de Goede * Also, why the hell we are returning early and not attempt to 1792*14ca7a47SHans de Goede * register video output if cooling device registration failed? 1793*14ca7a47SHans de Goede * -- dtor 1794*14ca7a47SHans de Goede */ 1795*14ca7a47SHans de Goede device->cooling_dev = NULL; 1796*14ca7a47SHans de Goede return; 1797*14ca7a47SHans de Goede } 1798*14ca7a47SHans de Goede 1799*14ca7a47SHans de Goede dev_info(&device->dev->dev, "registered as cooling_device%d\n", 1800*14ca7a47SHans de Goede device->cooling_dev->id); 1801*14ca7a47SHans de Goede result = sysfs_create_link(&device->dev->dev.kobj, 1802*14ca7a47SHans de Goede &device->cooling_dev->device.kobj, 1803*14ca7a47SHans de Goede "thermal_cooling"); 1804*14ca7a47SHans de Goede if (result) 1805*14ca7a47SHans de Goede printk(KERN_ERR PREFIX "Create sysfs link\n"); 1806*14ca7a47SHans de Goede result = sysfs_create_link(&device->cooling_dev->device.kobj, 1807*14ca7a47SHans de Goede &device->dev->dev.kobj, "device"); 1808*14ca7a47SHans de Goede if (result) 1809*14ca7a47SHans de Goede printk(KERN_ERR PREFIX "Create sysfs link\n"); 1810*14ca7a47SHans de Goede } 1811*14ca7a47SHans de Goede 1812*14ca7a47SHans de Goede static void acpi_video_run_bcl_for_osi(struct acpi_video_bus *video) 1813*14ca7a47SHans de Goede { 1814*14ca7a47SHans de Goede struct acpi_video_device *dev; 1815*14ca7a47SHans de Goede union acpi_object *levels; 1816*14ca7a47SHans de Goede 1817*14ca7a47SHans de Goede mutex_lock(&video->device_list_lock); 1818*14ca7a47SHans de Goede list_for_each_entry(dev, &video->video_device_list, entry) { 1819*14ca7a47SHans de Goede if (!acpi_video_device_lcd_query_levels(dev, &levels)) 1820*14ca7a47SHans de Goede kfree(levels); 1821*14ca7a47SHans de Goede } 1822*14ca7a47SHans de Goede mutex_unlock(&video->device_list_lock); 1823*14ca7a47SHans de Goede } 1824*14ca7a47SHans de Goede 1825*14ca7a47SHans de Goede static int acpi_video_bus_register_backlight(struct acpi_video_bus *video) 1826*14ca7a47SHans de Goede { 1827*14ca7a47SHans de Goede struct acpi_video_device *dev; 1828*14ca7a47SHans de Goede 1829*14ca7a47SHans de Goede if (video->backlight_registered) 1830*14ca7a47SHans de Goede return 0; 1831*14ca7a47SHans de Goede 1832*14ca7a47SHans de Goede acpi_video_run_bcl_for_osi(video); 1833*14ca7a47SHans de Goede 1834*14ca7a47SHans de Goede if (!acpi_video_verify_backlight_support()) 1835*14ca7a47SHans de Goede return 0; 1836*14ca7a47SHans de Goede 1837*14ca7a47SHans de Goede mutex_lock(&video->device_list_lock); 1838*14ca7a47SHans de Goede list_for_each_entry(dev, &video->video_device_list, entry) 1839*14ca7a47SHans de Goede acpi_video_dev_register_backlight(dev); 1840*14ca7a47SHans de Goede mutex_unlock(&video->device_list_lock); 1841*14ca7a47SHans de Goede 1842*14ca7a47SHans de Goede video->backlight_registered = true; 1843*14ca7a47SHans de Goede 1844*14ca7a47SHans de Goede video->pm_nb.notifier_call = acpi_video_resume; 1845*14ca7a47SHans de Goede video->pm_nb.priority = 0; 1846*14ca7a47SHans de Goede return register_pm_notifier(&video->pm_nb); 1847*14ca7a47SHans de Goede } 1848*14ca7a47SHans de Goede 1849*14ca7a47SHans de Goede static void acpi_video_dev_unregister_backlight(struct acpi_video_device *device) 1850*14ca7a47SHans de Goede { 1851*14ca7a47SHans de Goede if (device->backlight) { 1852*14ca7a47SHans de Goede backlight_device_unregister(device->backlight); 1853*14ca7a47SHans de Goede device->backlight = NULL; 1854*14ca7a47SHans de Goede } 1855*14ca7a47SHans de Goede if (device->brightness) { 1856*14ca7a47SHans de Goede kfree(device->brightness->levels); 1857*14ca7a47SHans de Goede kfree(device->brightness); 1858*14ca7a47SHans de Goede device->brightness = NULL; 1859*14ca7a47SHans de Goede } 1860*14ca7a47SHans de Goede if (device->cooling_dev) { 1861*14ca7a47SHans de Goede sysfs_remove_link(&device->dev->dev.kobj, "thermal_cooling"); 1862*14ca7a47SHans de Goede sysfs_remove_link(&device->cooling_dev->device.kobj, "device"); 1863*14ca7a47SHans de Goede thermal_cooling_device_unregister(device->cooling_dev); 1864*14ca7a47SHans de Goede device->cooling_dev = NULL; 1865*14ca7a47SHans de Goede } 1866*14ca7a47SHans de Goede } 1867*14ca7a47SHans de Goede 1868*14ca7a47SHans de Goede static int acpi_video_bus_unregister_backlight(struct acpi_video_bus *video) 1869*14ca7a47SHans de Goede { 1870*14ca7a47SHans de Goede struct acpi_video_device *dev; 1871*14ca7a47SHans de Goede int error; 1872*14ca7a47SHans de Goede 1873*14ca7a47SHans de Goede if (!video->backlight_registered) 1874*14ca7a47SHans de Goede return 0; 1875*14ca7a47SHans de Goede 1876*14ca7a47SHans de Goede error = unregister_pm_notifier(&video->pm_nb); 1877*14ca7a47SHans de Goede 1878*14ca7a47SHans de Goede mutex_lock(&video->device_list_lock); 1879*14ca7a47SHans de Goede list_for_each_entry(dev, &video->video_device_list, entry) 1880*14ca7a47SHans de Goede acpi_video_dev_unregister_backlight(dev); 1881*14ca7a47SHans de Goede mutex_unlock(&video->device_list_lock); 1882*14ca7a47SHans de Goede 1883*14ca7a47SHans de Goede video->backlight_registered = false; 1884*14ca7a47SHans de Goede 1885*14ca7a47SHans de Goede return error; 1886*14ca7a47SHans de Goede } 1887*14ca7a47SHans de Goede 1888*14ca7a47SHans de Goede static void acpi_video_dev_add_notify_handler(struct acpi_video_device *device) 1889*14ca7a47SHans de Goede { 1890*14ca7a47SHans de Goede acpi_status status; 1891*14ca7a47SHans de Goede struct acpi_device *adev = device->dev; 1892*14ca7a47SHans de Goede 1893*14ca7a47SHans de Goede status = acpi_install_notify_handler(adev->handle, ACPI_DEVICE_NOTIFY, 1894*14ca7a47SHans de Goede acpi_video_device_notify, device); 1895*14ca7a47SHans de Goede if (ACPI_FAILURE(status)) 1896*14ca7a47SHans de Goede dev_err(&adev->dev, "Error installing notify handler\n"); 1897*14ca7a47SHans de Goede else 1898*14ca7a47SHans de Goede device->flags.notify = 1; 1899*14ca7a47SHans de Goede } 1900*14ca7a47SHans de Goede 1901*14ca7a47SHans de Goede static int acpi_video_bus_add_notify_handler(struct acpi_video_bus *video) 1902*14ca7a47SHans de Goede { 1903*14ca7a47SHans de Goede struct input_dev *input; 1904*14ca7a47SHans de Goede struct acpi_video_device *dev; 1905*14ca7a47SHans de Goede int error; 1906*14ca7a47SHans de Goede 1907*14ca7a47SHans de Goede video->input = input = input_allocate_device(); 1908*14ca7a47SHans de Goede if (!input) { 1909*14ca7a47SHans de Goede error = -ENOMEM; 1910*14ca7a47SHans de Goede goto out; 1911*14ca7a47SHans de Goede } 1912*14ca7a47SHans de Goede 1913*14ca7a47SHans de Goede error = acpi_video_bus_start_devices(video); 1914*14ca7a47SHans de Goede if (error) 1915*14ca7a47SHans de Goede goto err_free_input; 1916*14ca7a47SHans de Goede 1917*14ca7a47SHans de Goede snprintf(video->phys, sizeof(video->phys), 1918*14ca7a47SHans de Goede "%s/video/input0", acpi_device_hid(video->device)); 1919*14ca7a47SHans de Goede 1920*14ca7a47SHans de Goede input->name = acpi_device_name(video->device); 1921*14ca7a47SHans de Goede input->phys = video->phys; 1922*14ca7a47SHans de Goede input->id.bustype = BUS_HOST; 1923*14ca7a47SHans de Goede input->id.product = 0x06; 1924*14ca7a47SHans de Goede input->dev.parent = &video->device->dev; 1925*14ca7a47SHans de Goede input->evbit[0] = BIT(EV_KEY); 1926*14ca7a47SHans de Goede set_bit(KEY_SWITCHVIDEOMODE, input->keybit); 1927*14ca7a47SHans de Goede set_bit(KEY_VIDEO_NEXT, input->keybit); 1928*14ca7a47SHans de Goede set_bit(KEY_VIDEO_PREV, input->keybit); 1929*14ca7a47SHans de Goede set_bit(KEY_BRIGHTNESS_CYCLE, input->keybit); 1930*14ca7a47SHans de Goede set_bit(KEY_BRIGHTNESSUP, input->keybit); 1931*14ca7a47SHans de Goede set_bit(KEY_BRIGHTNESSDOWN, input->keybit); 1932*14ca7a47SHans de Goede set_bit(KEY_BRIGHTNESS_ZERO, input->keybit); 1933*14ca7a47SHans de Goede set_bit(KEY_DISPLAY_OFF, input->keybit); 1934*14ca7a47SHans de Goede 1935*14ca7a47SHans de Goede error = input_register_device(input); 1936*14ca7a47SHans de Goede if (error) 1937*14ca7a47SHans de Goede goto err_stop_dev; 1938*14ca7a47SHans de Goede 1939*14ca7a47SHans de Goede mutex_lock(&video->device_list_lock); 1940*14ca7a47SHans de Goede list_for_each_entry(dev, &video->video_device_list, entry) 1941*14ca7a47SHans de Goede acpi_video_dev_add_notify_handler(dev); 1942*14ca7a47SHans de Goede mutex_unlock(&video->device_list_lock); 1943*14ca7a47SHans de Goede 1944*14ca7a47SHans de Goede return 0; 1945*14ca7a47SHans de Goede 1946*14ca7a47SHans de Goede err_stop_dev: 1947*14ca7a47SHans de Goede acpi_video_bus_stop_devices(video); 1948*14ca7a47SHans de Goede err_free_input: 1949*14ca7a47SHans de Goede input_free_device(input); 1950*14ca7a47SHans de Goede video->input = NULL; 1951*14ca7a47SHans de Goede out: 1952*14ca7a47SHans de Goede return error; 1953*14ca7a47SHans de Goede } 1954*14ca7a47SHans de Goede 1955*14ca7a47SHans de Goede static void acpi_video_dev_remove_notify_handler(struct acpi_video_device *dev) 1956*14ca7a47SHans de Goede { 1957*14ca7a47SHans de Goede if (dev->flags.notify) { 1958*14ca7a47SHans de Goede acpi_remove_notify_handler(dev->dev->handle, ACPI_DEVICE_NOTIFY, 1959*14ca7a47SHans de Goede acpi_video_device_notify); 1960*14ca7a47SHans de Goede dev->flags.notify = 0; 1961*14ca7a47SHans de Goede } 1962*14ca7a47SHans de Goede } 1963*14ca7a47SHans de Goede 1964*14ca7a47SHans de Goede static void acpi_video_bus_remove_notify_handler(struct acpi_video_bus *video) 1965*14ca7a47SHans de Goede { 1966*14ca7a47SHans de Goede struct acpi_video_device *dev; 1967*14ca7a47SHans de Goede 1968*14ca7a47SHans de Goede mutex_lock(&video->device_list_lock); 1969*14ca7a47SHans de Goede list_for_each_entry(dev, &video->video_device_list, entry) 1970*14ca7a47SHans de Goede acpi_video_dev_remove_notify_handler(dev); 1971*14ca7a47SHans de Goede mutex_unlock(&video->device_list_lock); 1972*14ca7a47SHans de Goede 1973*14ca7a47SHans de Goede acpi_video_bus_stop_devices(video); 1974*14ca7a47SHans de Goede input_unregister_device(video->input); 1975*14ca7a47SHans de Goede video->input = NULL; 1976*14ca7a47SHans de Goede } 1977*14ca7a47SHans de Goede 1978*14ca7a47SHans de Goede static int acpi_video_backlight_notify(struct notifier_block *nb, 1979*14ca7a47SHans de Goede unsigned long val, void *bd) 1980*14ca7a47SHans de Goede { 1981*14ca7a47SHans de Goede struct backlight_device *backlight = bd; 1982*14ca7a47SHans de Goede struct acpi_video_bus *video; 1983*14ca7a47SHans de Goede 1984*14ca7a47SHans de Goede /* acpi_video_verify_backlight_support only cares about raw devices */ 1985*14ca7a47SHans de Goede if (backlight->props.type != BACKLIGHT_RAW) 1986*14ca7a47SHans de Goede return NOTIFY_DONE; 1987*14ca7a47SHans de Goede 1988*14ca7a47SHans de Goede video = container_of(nb, struct acpi_video_bus, backlight_nb); 1989*14ca7a47SHans de Goede 1990*14ca7a47SHans de Goede switch (val) { 1991*14ca7a47SHans de Goede case BACKLIGHT_REGISTERED: 1992*14ca7a47SHans de Goede if (!acpi_video_verify_backlight_support()) 1993*14ca7a47SHans de Goede acpi_video_bus_unregister_backlight(video); 1994*14ca7a47SHans de Goede break; 1995*14ca7a47SHans de Goede case BACKLIGHT_UNREGISTERED: 1996*14ca7a47SHans de Goede acpi_video_bus_register_backlight(video); 1997*14ca7a47SHans de Goede break; 1998*14ca7a47SHans de Goede } 1999*14ca7a47SHans de Goede 2000*14ca7a47SHans de Goede return NOTIFY_OK; 2001*14ca7a47SHans de Goede } 2002*14ca7a47SHans de Goede 2003*14ca7a47SHans de Goede static int acpi_video_bus_add_backlight_notify_handler( 2004*14ca7a47SHans de Goede struct acpi_video_bus *video) 2005*14ca7a47SHans de Goede { 2006*14ca7a47SHans de Goede int error; 2007*14ca7a47SHans de Goede 2008*14ca7a47SHans de Goede video->backlight_nb.notifier_call = acpi_video_backlight_notify; 2009*14ca7a47SHans de Goede video->backlight_nb.priority = 0; 2010*14ca7a47SHans de Goede error = backlight_register_notifier(&video->backlight_nb); 2011*14ca7a47SHans de Goede if (error == 0) 2012*14ca7a47SHans de Goede video->backlight_notifier_registered = true; 2013*14ca7a47SHans de Goede 2014*14ca7a47SHans de Goede return error; 2015*14ca7a47SHans de Goede } 2016*14ca7a47SHans de Goede 2017*14ca7a47SHans de Goede static int acpi_video_bus_remove_backlight_notify_handler( 2018*14ca7a47SHans de Goede struct acpi_video_bus *video) 2019*14ca7a47SHans de Goede { 2020*14ca7a47SHans de Goede if (!video->backlight_notifier_registered) 2021*14ca7a47SHans de Goede return 0; 2022*14ca7a47SHans de Goede 2023*14ca7a47SHans de Goede video->backlight_notifier_registered = false; 2024*14ca7a47SHans de Goede 2025*14ca7a47SHans de Goede return backlight_unregister_notifier(&video->backlight_nb); 2026*14ca7a47SHans de Goede } 2027*14ca7a47SHans de Goede 2028*14ca7a47SHans de Goede static int acpi_video_bus_put_devices(struct acpi_video_bus *video) 2029*14ca7a47SHans de Goede { 2030*14ca7a47SHans de Goede struct acpi_video_device *dev, *next; 2031*14ca7a47SHans de Goede 2032*14ca7a47SHans de Goede mutex_lock(&video->device_list_lock); 2033*14ca7a47SHans de Goede list_for_each_entry_safe(dev, next, &video->video_device_list, entry) { 2034*14ca7a47SHans de Goede list_del(&dev->entry); 2035*14ca7a47SHans de Goede kfree(dev); 2036*14ca7a47SHans de Goede } 2037*14ca7a47SHans de Goede mutex_unlock(&video->device_list_lock); 2038*14ca7a47SHans de Goede 2039*14ca7a47SHans de Goede return 0; 2040*14ca7a47SHans de Goede } 2041*14ca7a47SHans de Goede 2042*14ca7a47SHans de Goede static int instance; 2043*14ca7a47SHans de Goede 2044*14ca7a47SHans de Goede static int acpi_video_bus_add(struct acpi_device *device) 2045*14ca7a47SHans de Goede { 2046*14ca7a47SHans de Goede struct acpi_video_bus *video; 2047*14ca7a47SHans de Goede int error; 2048*14ca7a47SHans de Goede acpi_status status; 2049*14ca7a47SHans de Goede 2050*14ca7a47SHans de Goede status = acpi_walk_namespace(ACPI_TYPE_DEVICE, 2051*14ca7a47SHans de Goede device->parent->handle, 1, 2052*14ca7a47SHans de Goede acpi_video_bus_match, NULL, 2053*14ca7a47SHans de Goede device, NULL); 2054*14ca7a47SHans de Goede if (status == AE_ALREADY_EXISTS) { 2055*14ca7a47SHans de Goede printk(KERN_WARNING FW_BUG 2056*14ca7a47SHans de Goede "Duplicate ACPI video bus devices for the" 2057*14ca7a47SHans de Goede " same VGA controller, please try module " 2058*14ca7a47SHans de Goede "parameter \"video.allow_duplicates=1\"" 2059*14ca7a47SHans de Goede "if the current driver doesn't work.\n"); 2060*14ca7a47SHans de Goede if (!allow_duplicates) 2061*14ca7a47SHans de Goede return -ENODEV; 2062*14ca7a47SHans de Goede } 2063*14ca7a47SHans de Goede 2064*14ca7a47SHans de Goede video = kzalloc(sizeof(struct acpi_video_bus), GFP_KERNEL); 2065*14ca7a47SHans de Goede if (!video) 2066*14ca7a47SHans de Goede return -ENOMEM; 2067*14ca7a47SHans de Goede 2068*14ca7a47SHans de Goede /* a hack to fix the duplicate name "VID" problem on T61 */ 2069*14ca7a47SHans de Goede if (!strcmp(device->pnp.bus_id, "VID")) { 2070*14ca7a47SHans de Goede if (instance) 2071*14ca7a47SHans de Goede device->pnp.bus_id[3] = '0' + instance; 2072*14ca7a47SHans de Goede instance++; 2073*14ca7a47SHans de Goede } 2074*14ca7a47SHans de Goede /* a hack to fix the duplicate name "VGA" problem on Pa 3553 */ 2075*14ca7a47SHans de Goede if (!strcmp(device->pnp.bus_id, "VGA")) { 2076*14ca7a47SHans de Goede if (instance) 2077*14ca7a47SHans de Goede device->pnp.bus_id[3] = '0' + instance; 2078*14ca7a47SHans de Goede instance++; 2079*14ca7a47SHans de Goede } 2080*14ca7a47SHans de Goede 2081*14ca7a47SHans de Goede video->device = device; 2082*14ca7a47SHans de Goede strcpy(acpi_device_name(device), ACPI_VIDEO_BUS_NAME); 2083*14ca7a47SHans de Goede strcpy(acpi_device_class(device), ACPI_VIDEO_CLASS); 2084*14ca7a47SHans de Goede device->driver_data = video; 2085*14ca7a47SHans de Goede 2086*14ca7a47SHans de Goede acpi_video_bus_find_cap(video); 2087*14ca7a47SHans de Goede error = acpi_video_bus_check(video); 2088*14ca7a47SHans de Goede if (error) 2089*14ca7a47SHans de Goede goto err_free_video; 2090*14ca7a47SHans de Goede 2091*14ca7a47SHans de Goede mutex_init(&video->device_list_lock); 2092*14ca7a47SHans de Goede INIT_LIST_HEAD(&video->video_device_list); 2093*14ca7a47SHans de Goede 2094*14ca7a47SHans de Goede error = acpi_video_bus_get_devices(video, device); 2095*14ca7a47SHans de Goede if (error) 2096*14ca7a47SHans de Goede goto err_put_video; 2097*14ca7a47SHans de Goede 2098*14ca7a47SHans de Goede printk(KERN_INFO PREFIX "%s [%s] (multi-head: %s rom: %s post: %s)\n", 2099*14ca7a47SHans de Goede ACPI_VIDEO_DEVICE_NAME, acpi_device_bid(device), 2100*14ca7a47SHans de Goede video->flags.multihead ? "yes" : "no", 2101*14ca7a47SHans de Goede video->flags.rom ? "yes" : "no", 2102*14ca7a47SHans de Goede video->flags.post ? "yes" : "no"); 2103*14ca7a47SHans de Goede mutex_lock(&video_list_lock); 2104*14ca7a47SHans de Goede list_add_tail(&video->entry, &video_bus_head); 2105*14ca7a47SHans de Goede mutex_unlock(&video_list_lock); 2106*14ca7a47SHans de Goede 2107*14ca7a47SHans de Goede acpi_video_bus_register_backlight(video); 2108*14ca7a47SHans de Goede acpi_video_bus_add_notify_handler(video); 2109*14ca7a47SHans de Goede acpi_video_bus_add_backlight_notify_handler(video); 2110*14ca7a47SHans de Goede 2111*14ca7a47SHans de Goede return 0; 2112*14ca7a47SHans de Goede 2113*14ca7a47SHans de Goede err_put_video: 2114*14ca7a47SHans de Goede acpi_video_bus_put_devices(video); 2115*14ca7a47SHans de Goede kfree(video->attached_array); 2116*14ca7a47SHans de Goede err_free_video: 2117*14ca7a47SHans de Goede kfree(video); 2118*14ca7a47SHans de Goede device->driver_data = NULL; 2119*14ca7a47SHans de Goede 2120*14ca7a47SHans de Goede return error; 2121*14ca7a47SHans de Goede } 2122*14ca7a47SHans de Goede 2123*14ca7a47SHans de Goede static int acpi_video_bus_remove(struct acpi_device *device) 2124*14ca7a47SHans de Goede { 2125*14ca7a47SHans de Goede struct acpi_video_bus *video = NULL; 2126*14ca7a47SHans de Goede 2127*14ca7a47SHans de Goede 2128*14ca7a47SHans de Goede if (!device || !acpi_driver_data(device)) 2129*14ca7a47SHans de Goede return -EINVAL; 2130*14ca7a47SHans de Goede 2131*14ca7a47SHans de Goede video = acpi_driver_data(device); 2132*14ca7a47SHans de Goede 2133*14ca7a47SHans de Goede acpi_video_bus_remove_backlight_notify_handler(video); 2134*14ca7a47SHans de Goede acpi_video_bus_remove_notify_handler(video); 2135*14ca7a47SHans de Goede acpi_video_bus_unregister_backlight(video); 2136*14ca7a47SHans de Goede acpi_video_bus_put_devices(video); 2137*14ca7a47SHans de Goede 2138*14ca7a47SHans de Goede mutex_lock(&video_list_lock); 2139*14ca7a47SHans de Goede list_del(&video->entry); 2140*14ca7a47SHans de Goede mutex_unlock(&video_list_lock); 2141*14ca7a47SHans de Goede 2142*14ca7a47SHans de Goede kfree(video->attached_array); 2143*14ca7a47SHans de Goede kfree(video); 2144*14ca7a47SHans de Goede 2145*14ca7a47SHans de Goede return 0; 2146*14ca7a47SHans de Goede } 2147*14ca7a47SHans de Goede 2148*14ca7a47SHans de Goede static int __init is_i740(struct pci_dev *dev) 2149*14ca7a47SHans de Goede { 2150*14ca7a47SHans de Goede if (dev->device == 0x00D1) 2151*14ca7a47SHans de Goede return 1; 2152*14ca7a47SHans de Goede if (dev->device == 0x7000) 2153*14ca7a47SHans de Goede return 1; 2154*14ca7a47SHans de Goede return 0; 2155*14ca7a47SHans de Goede } 2156*14ca7a47SHans de Goede 2157*14ca7a47SHans de Goede static int __init intel_opregion_present(void) 2158*14ca7a47SHans de Goede { 2159*14ca7a47SHans de Goede int opregion = 0; 2160*14ca7a47SHans de Goede struct pci_dev *dev = NULL; 2161*14ca7a47SHans de Goede u32 address; 2162*14ca7a47SHans de Goede 2163*14ca7a47SHans de Goede for_each_pci_dev(dev) { 2164*14ca7a47SHans de Goede if ((dev->class >> 8) != PCI_CLASS_DISPLAY_VGA) 2165*14ca7a47SHans de Goede continue; 2166*14ca7a47SHans de Goede if (dev->vendor != PCI_VENDOR_ID_INTEL) 2167*14ca7a47SHans de Goede continue; 2168*14ca7a47SHans de Goede /* We don't want to poke around undefined i740 registers */ 2169*14ca7a47SHans de Goede if (is_i740(dev)) 2170*14ca7a47SHans de Goede continue; 2171*14ca7a47SHans de Goede pci_read_config_dword(dev, 0xfc, &address); 2172*14ca7a47SHans de Goede if (!address) 2173*14ca7a47SHans de Goede continue; 2174*14ca7a47SHans de Goede opregion = 1; 2175*14ca7a47SHans de Goede } 2176*14ca7a47SHans de Goede return opregion; 2177*14ca7a47SHans de Goede } 2178*14ca7a47SHans de Goede 2179*14ca7a47SHans de Goede int acpi_video_register(void) 2180*14ca7a47SHans de Goede { 2181*14ca7a47SHans de Goede int ret; 2182*14ca7a47SHans de Goede 2183*14ca7a47SHans de Goede if (register_count) { 2184*14ca7a47SHans de Goede /* 2185*14ca7a47SHans de Goede * if the function of acpi_video_register is already called, 2186*14ca7a47SHans de Goede * don't register the acpi_vide_bus again and return no error. 2187*14ca7a47SHans de Goede */ 2188*14ca7a47SHans de Goede return 0; 2189*14ca7a47SHans de Goede } 2190*14ca7a47SHans de Goede 2191*14ca7a47SHans de Goede mutex_init(&video_list_lock); 2192*14ca7a47SHans de Goede INIT_LIST_HEAD(&video_bus_head); 2193*14ca7a47SHans de Goede 2194*14ca7a47SHans de Goede ret = acpi_bus_register_driver(&acpi_video_bus); 2195*14ca7a47SHans de Goede if (ret) 2196*14ca7a47SHans de Goede return ret; 2197*14ca7a47SHans de Goede 2198*14ca7a47SHans de Goede /* 2199*14ca7a47SHans de Goede * When the acpi_video_bus is loaded successfully, increase 2200*14ca7a47SHans de Goede * the counter reference. 2201*14ca7a47SHans de Goede */ 2202*14ca7a47SHans de Goede register_count = 1; 2203*14ca7a47SHans de Goede 2204*14ca7a47SHans de Goede return 0; 2205*14ca7a47SHans de Goede } 2206*14ca7a47SHans de Goede EXPORT_SYMBOL(acpi_video_register); 2207*14ca7a47SHans de Goede 2208*14ca7a47SHans de Goede void acpi_video_unregister(void) 2209*14ca7a47SHans de Goede { 2210*14ca7a47SHans de Goede if (!register_count) { 2211*14ca7a47SHans de Goede /* 2212*14ca7a47SHans de Goede * If the acpi video bus is already unloaded, don't 2213*14ca7a47SHans de Goede * unload it again and return directly. 2214*14ca7a47SHans de Goede */ 2215*14ca7a47SHans de Goede return; 2216*14ca7a47SHans de Goede } 2217*14ca7a47SHans de Goede acpi_bus_unregister_driver(&acpi_video_bus); 2218*14ca7a47SHans de Goede 2219*14ca7a47SHans de Goede register_count = 0; 2220*14ca7a47SHans de Goede 2221*14ca7a47SHans de Goede return; 2222*14ca7a47SHans de Goede } 2223*14ca7a47SHans de Goede EXPORT_SYMBOL(acpi_video_unregister); 2224*14ca7a47SHans de Goede 2225*14ca7a47SHans de Goede void acpi_video_unregister_backlight(void) 2226*14ca7a47SHans de Goede { 2227*14ca7a47SHans de Goede struct acpi_video_bus *video; 2228*14ca7a47SHans de Goede 2229*14ca7a47SHans de Goede if (!register_count) 2230*14ca7a47SHans de Goede return; 2231*14ca7a47SHans de Goede 2232*14ca7a47SHans de Goede mutex_lock(&video_list_lock); 2233*14ca7a47SHans de Goede list_for_each_entry(video, &video_bus_head, entry) 2234*14ca7a47SHans de Goede acpi_video_bus_unregister_backlight(video); 2235*14ca7a47SHans de Goede mutex_unlock(&video_list_lock); 2236*14ca7a47SHans de Goede } 2237*14ca7a47SHans de Goede EXPORT_SYMBOL(acpi_video_unregister_backlight); 2238*14ca7a47SHans de Goede 2239*14ca7a47SHans de Goede /* 2240*14ca7a47SHans de Goede * This is kind of nasty. Hardware using Intel chipsets may require 2241*14ca7a47SHans de Goede * the video opregion code to be run first in order to initialise 2242*14ca7a47SHans de Goede * state before any ACPI video calls are made. To handle this we defer 2243*14ca7a47SHans de Goede * registration of the video class until the opregion code has run. 2244*14ca7a47SHans de Goede */ 2245*14ca7a47SHans de Goede 2246*14ca7a47SHans de Goede static int __init acpi_video_init(void) 2247*14ca7a47SHans de Goede { 2248*14ca7a47SHans de Goede /* 2249*14ca7a47SHans de Goede * Let the module load even if ACPI is disabled (e.g. due to 2250*14ca7a47SHans de Goede * a broken BIOS) so that i915.ko can still be loaded on such 2251*14ca7a47SHans de Goede * old systems without an AcpiOpRegion. 2252*14ca7a47SHans de Goede * 2253*14ca7a47SHans de Goede * acpi_video_register() will report -ENODEV later as well due 2254*14ca7a47SHans de Goede * to acpi_disabled when i915.ko tries to register itself afterwards. 2255*14ca7a47SHans de Goede */ 2256*14ca7a47SHans de Goede if (acpi_disabled) 2257*14ca7a47SHans de Goede return 0; 2258*14ca7a47SHans de Goede 2259*14ca7a47SHans de Goede dmi_check_system(video_dmi_table); 2260*14ca7a47SHans de Goede 2261*14ca7a47SHans de Goede if (intel_opregion_present()) 2262*14ca7a47SHans de Goede return 0; 2263*14ca7a47SHans de Goede 2264*14ca7a47SHans de Goede return acpi_video_register(); 2265*14ca7a47SHans de Goede } 2266*14ca7a47SHans de Goede 2267*14ca7a47SHans de Goede static void __exit acpi_video_exit(void) 2268*14ca7a47SHans de Goede { 2269*14ca7a47SHans de Goede acpi_video_unregister(); 2270*14ca7a47SHans de Goede 2271*14ca7a47SHans de Goede return; 2272*14ca7a47SHans de Goede } 2273*14ca7a47SHans de Goede 2274*14ca7a47SHans de Goede module_init(acpi_video_init); 2275*14ca7a47SHans de Goede module_exit(acpi_video_exit); 2276