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