]>
Commit | Line | Data |
---|---|---|
2cb7cef9 BS |
1 | From: Thomas Renninger <trenn@stravinsky.suse.de> |
2 | Subject: Serve ThinkPad IGD devices backlight functionality through thinkpad_acpi | |
3 | References: fate #302883 | |
4 | ||
5 | In future IDG devices will be handled by the dri subsystem. | |
6 | But this code is very young and complex, better workaround this in | |
7 | thinkpad_acpi driver for now. | |
8 | ||
9 | If in a later service pack the IGD parts get backported, this patch must | |
10 | be reverted. | |
11 | ||
12 | Signed-off-by: Thomas Renninger <trenn@suse.de> | |
13 | --- | |
14 | drivers/acpi/video_detect.c | 15 +++++++++++++++ | |
15 | drivers/misc/thinkpad_acpi.c | 40 ++++++++++++++++++++++++++++++++++++---- | |
16 | include/linux/acpi.h | 2 ++ | |
17 | 3 files changed, 53 insertions(+), 4 deletions(-) | |
18 | ||
19 | --- a/drivers/acpi/video_detect.c | |
20 | +++ b/drivers/acpi/video_detect.c | |
21 | @@ -99,6 +99,21 @@ long acpi_is_video_device(struct acpi_de | |
22 | ACPI_UINT32_MAX, acpi_backlight_cap_match, | |
23 | &video_caps, NULL); | |
24 | ||
25 | + /* IGD detection is not perfect. It should use the same method as done | |
26 | + * to identify an IGD device in the dri parts or video.ko | |
27 | + */ | |
28 | + | |
29 | + /* | |
30 | + * ThinkPads do need the IGD implementation, we detect ThinkPad IGD | |
31 | + * devices here and specially workaround it in thinkpad_acpi as the | |
32 | + * IGD parts are too experimental yet | |
33 | + */ | |
34 | + if (dmi_name_in_vendors("LENOVO") && | |
35 | + ACPI_SUCCESS(acpi_get_handle(device->handle, "DRDY", &h_dummy))) { | |
36 | + ACPI_DEBUG_PRINT((ACPI_DB_INFO, "Found IGD device\n")); | |
37 | + video_caps |= ACPI_VIDEO_IGD; | |
38 | + } | |
39 | + | |
40 | return video_caps; | |
41 | } | |
42 | EXPORT_SYMBOL(acpi_is_video_device); | |
43 | --- a/drivers/misc/thinkpad_acpi.c | |
44 | +++ b/drivers/misc/thinkpad_acpi.c | |
45 | @@ -240,6 +240,7 @@ static struct { | |
46 | u32 light_status:1; | |
47 | u32 bright_16levels:1; | |
48 | u32 bright_acpimode:1; | |
49 | + u32 bright_igdmode:1; | |
50 | u32 wan:1; | |
51 | u32 fan_ctrl_status_undef:1; | |
52 | u32 input_device_registered:1; | |
53 | @@ -2359,6 +2360,9 @@ err_exit: | |
54 | return (res < 0)? res : 1; | |
55 | } | |
56 | ||
57 | +static struct backlight_device *ibm_backlight_device; | |
58 | +static int brightness_update_status(struct backlight_device *bd); | |
59 | + | |
60 | static void hotkey_notify(struct ibm_struct *ibm, u32 event) | |
61 | { | |
62 | u32 hkey; | |
63 | @@ -2397,6 +2401,28 @@ static void hotkey_notify(struct ibm_str | |
64 | case 1: | |
65 | /* 0x1000-0x1FFF: key presses */ | |
66 | scancode = hkey & 0xfff; | |
67 | + if (tp_features.bright_igdmode) { | |
68 | + /* ToDo: | |
69 | + * Is there an already defined key? | |
70 | + */ | |
71 | + if (hkey == 0x1011) { | |
72 | + if (ibm_backlight_device-> | |
73 | + props.brightness > 0) { | |
74 | + ibm_backlight_device-> | |
75 | + props.brightness--; | |
76 | + } | |
77 | + } else if (hkey == 0x1010) { | |
78 | + if (ibm_backlight_device-> | |
79 | + props.brightness < | |
80 | + ibm_backlight_device-> | |
81 | + props.max_brightness) { | |
82 | + ibm_backlight_device-> | |
83 | + props.brightness++; | |
84 | + } | |
85 | + } | |
86 | + brightness_update_status(ibm_backlight_device); | |
87 | + } | |
88 | + | |
89 | if (scancode > 0 && scancode < 0x21) { | |
90 | scancode--; | |
91 | if (!(hotkey_source_mask & (1 << scancode))) { | |
92 | @@ -4767,7 +4793,6 @@ enum { | |
93 | TP_EC_BACKLIGHT_MAPSW = 0x20, | |
94 | }; | |
95 | ||
96 | -static struct backlight_device *ibm_backlight_device; | |
97 | static int brightness_mode; | |
98 | static unsigned int brightness_enable = 2; /* 2 = auto, 0 = no, 1 = yes */ | |
99 | ||
100 | @@ -4906,7 +4931,7 @@ static struct backlight_ops ibm_backligh | |
101 | static int __init brightness_init(struct ibm_init_struct *iibm) | |
102 | { | |
103 | int b; | |
104 | - | |
105 | + long acpi_video_support; | |
106 | vdbg_printk(TPACPI_DBG_INIT, "initializing brightness subdriver\n"); | |
107 | ||
108 | mutex_init(&brightness_mutex); | |
109 | @@ -4918,8 +4943,9 @@ static int __init brightness_init(struct | |
110 | */ | |
111 | b = tpacpi_check_std_acpi_brightness_support(); | |
112 | if (b > 0) { | |
113 | - | |
114 | - if (acpi_video_backlight_support()) { | |
115 | + acpi_video_support = acpi_video_backlight_support(); | |
116 | + if (acpi_video_support && | |
117 | + !(acpi_video_support & ACPI_VIDEO_IGD)) { | |
118 | if (brightness_enable > 1) { | |
119 | printk(TPACPI_NOTICE | |
120 | "Standard ACPI backlight interface " | |
121 | @@ -4937,6 +4963,12 @@ static int __init brightness_init(struct | |
122 | "available, thinkpad_acpi driver " | |
123 | "will take over control\n"); | |
124 | } | |
125 | + if (acpi_video_support & ACPI_VIDEO_IGD) { | |
126 | + printk(TPACPI_NOTICE, "IGD device" | |
127 | + " detected - take over backlight" | |
128 | + " switching\n"); | |
129 | + tp_features.bright_igdmode = 1; | |
130 | + } | |
131 | } | |
132 | } | |
133 | ||
134 | --- a/include/linux/acpi.h | |
135 | +++ b/include/linux/acpi.h | |
136 | @@ -214,6 +214,8 @@ extern bool wmi_has_guid(const char *gui | |
137 | #define ACPI_VIDEO_BACKLIGHT_DMI_VIDEO 0x0200 | |
138 | #define ACPI_VIDEO_OUTPUT_SWITCHING_DMI_VENDOR 0x0400 | |
139 | #define ACPI_VIDEO_OUTPUT_SWITCHING_DMI_VIDEO 0x0800 | |
140 | +/* Do not use the IGD define, this is a SUSE only ThinkPad workaround hack! */ | |
141 | +#define ACPI_VIDEO_IGD 0x1000 | |
142 | ||
143 | #if defined(CONFIG_ACPI_VIDEO) || defined(CONFIG_ACPI_VIDEO_MODULE) | |
144 |