aboutsummaryrefslogtreecommitdiffstats
path: root/drivers/platform/x86/thinkpad_acpi.c
diff options
context:
space:
mode:
Diffstat (limited to 'drivers/platform/x86/thinkpad_acpi.c')
-rw-r--r--drivers/platform/x86/thinkpad_acpi.c171
1 files changed, 88 insertions, 83 deletions
diff --git a/drivers/platform/x86/thinkpad_acpi.c b/drivers/platform/x86/thinkpad_acpi.c
index 5d6119bed00c..e35ed128bdef 100644
--- a/drivers/platform/x86/thinkpad_acpi.c
+++ b/drivers/platform/x86/thinkpad_acpi.c
@@ -1911,6 +1911,17 @@ enum { /* hot key scan codes (derived from ACPI DSDT) */
1911 TP_ACPI_HOTKEYSCAN_VOLUMEDOWN, 1911 TP_ACPI_HOTKEYSCAN_VOLUMEDOWN,
1912 TP_ACPI_HOTKEYSCAN_MUTE, 1912 TP_ACPI_HOTKEYSCAN_MUTE,
1913 TP_ACPI_HOTKEYSCAN_THINKPAD, 1913 TP_ACPI_HOTKEYSCAN_THINKPAD,
1914 TP_ACPI_HOTKEYSCAN_UNK1,
1915 TP_ACPI_HOTKEYSCAN_UNK2,
1916 TP_ACPI_HOTKEYSCAN_UNK3,
1917 TP_ACPI_HOTKEYSCAN_UNK4,
1918 TP_ACPI_HOTKEYSCAN_UNK5,
1919 TP_ACPI_HOTKEYSCAN_UNK6,
1920 TP_ACPI_HOTKEYSCAN_UNK7,
1921 TP_ACPI_HOTKEYSCAN_UNK8,
1922
1923 /* Hotkey keymap size */
1924 TPACPI_HOTKEY_MAP_LEN
1914}; 1925};
1915 1926
1916enum { /* Keys/events available through NVRAM polling */ 1927enum { /* Keys/events available through NVRAM polling */
@@ -3082,6 +3093,8 @@ static const struct tpacpi_quirk tpacpi_hotkey_qtable[] __initconst = {
3082 TPACPI_Q_IBM('1', 'D', TPACPI_HK_Q_INIMASK), /* X22, X23, X24 */ 3093 TPACPI_Q_IBM('1', 'D', TPACPI_HK_Q_INIMASK), /* X22, X23, X24 */
3083}; 3094};
3084 3095
3096typedef u16 tpacpi_keymap_t[TPACPI_HOTKEY_MAP_LEN];
3097
3085static int __init hotkey_init(struct ibm_init_struct *iibm) 3098static int __init hotkey_init(struct ibm_init_struct *iibm)
3086{ 3099{
3087 /* Requirements for changing the default keymaps: 3100 /* Requirements for changing the default keymaps:
@@ -3113,9 +3126,17 @@ static int __init hotkey_init(struct ibm_init_struct *iibm)
3113 * If the above is too much to ask, don't change the keymap. 3126 * If the above is too much to ask, don't change the keymap.
3114 * Ask the thinkpad-acpi maintainer to do it, instead. 3127 * Ask the thinkpad-acpi maintainer to do it, instead.
3115 */ 3128 */
3116 static u16 ibm_keycode_map[] __initdata = { 3129
3130 enum keymap_index {
3131 TPACPI_KEYMAP_IBM_GENERIC = 0,
3132 TPACPI_KEYMAP_LENOVO_GENERIC,
3133 };
3134
3135 static const tpacpi_keymap_t tpacpi_keymaps[] __initconst = {
3136 /* Generic keymap for IBM ThinkPads */
3137 [TPACPI_KEYMAP_IBM_GENERIC] = {
3117 /* Scan Codes 0x00 to 0x0B: ACPI HKEY FN+F1..F12 */ 3138 /* Scan Codes 0x00 to 0x0B: ACPI HKEY FN+F1..F12 */
3118 KEY_FN_F1, KEY_FN_F2, KEY_COFFEE, KEY_SLEEP, 3139 KEY_FN_F1, KEY_BATTERY, KEY_COFFEE, KEY_SLEEP,
3119 KEY_WLAN, KEY_FN_F6, KEY_SWITCHVIDEOMODE, KEY_FN_F8, 3140 KEY_WLAN, KEY_FN_F6, KEY_SWITCHVIDEOMODE, KEY_FN_F8,
3120 KEY_FN_F9, KEY_FN_F10, KEY_FN_F11, KEY_SUSPEND, 3141 KEY_FN_F9, KEY_FN_F10, KEY_FN_F11, KEY_SUSPEND,
3121 3142
@@ -3146,11 +3167,13 @@ static int __init hotkey_init(struct ibm_init_struct *iibm)
3146 /* (assignments unknown, please report if found) */ 3167 /* (assignments unknown, please report if found) */
3147 KEY_UNKNOWN, KEY_UNKNOWN, KEY_UNKNOWN, KEY_UNKNOWN, 3168 KEY_UNKNOWN, KEY_UNKNOWN, KEY_UNKNOWN, KEY_UNKNOWN,
3148 KEY_UNKNOWN, KEY_UNKNOWN, KEY_UNKNOWN, KEY_UNKNOWN, 3169 KEY_UNKNOWN, KEY_UNKNOWN, KEY_UNKNOWN, KEY_UNKNOWN,
3149 }; 3170 },
3150 static u16 lenovo_keycode_map[] __initdata = { 3171
3172 /* Generic keymap for Lenovo ThinkPads */
3173 [TPACPI_KEYMAP_LENOVO_GENERIC] = {
3151 /* Scan Codes 0x00 to 0x0B: ACPI HKEY FN+F1..F12 */ 3174 /* Scan Codes 0x00 to 0x0B: ACPI HKEY FN+F1..F12 */
3152 KEY_FN_F1, KEY_COFFEE, KEY_BATTERY, KEY_SLEEP, 3175 KEY_FN_F1, KEY_COFFEE, KEY_BATTERY, KEY_SLEEP,
3153 KEY_WLAN, KEY_FN_F6, KEY_SWITCHVIDEOMODE, KEY_FN_F8, 3176 KEY_WLAN, KEY_CAMERA, KEY_SWITCHVIDEOMODE, KEY_FN_F8,
3154 KEY_FN_F9, KEY_FN_F10, KEY_FN_F11, KEY_SUSPEND, 3177 KEY_FN_F9, KEY_FN_F10, KEY_FN_F11, KEY_SUSPEND,
3155 3178
3156 /* Scan codes 0x0C to 0x1F: Other ACPI HKEY hot keys */ 3179 /* Scan codes 0x0C to 0x1F: Other ACPI HKEY hot keys */
@@ -3189,11 +3212,25 @@ static int __init hotkey_init(struct ibm_init_struct *iibm)
3189 /* (assignments unknown, please report if found) */ 3212 /* (assignments unknown, please report if found) */
3190 KEY_UNKNOWN, KEY_UNKNOWN, KEY_UNKNOWN, KEY_UNKNOWN, 3213 KEY_UNKNOWN, KEY_UNKNOWN, KEY_UNKNOWN, KEY_UNKNOWN,
3191 KEY_UNKNOWN, KEY_UNKNOWN, KEY_UNKNOWN, KEY_UNKNOWN, 3214 KEY_UNKNOWN, KEY_UNKNOWN, KEY_UNKNOWN, KEY_UNKNOWN,
3215 },
3216 };
3217
3218 static const struct tpacpi_quirk tpacpi_keymap_qtable[] __initconst = {
3219 /* Generic maps (fallback) */
3220 {
3221 .vendor = PCI_VENDOR_ID_IBM,
3222 .bios = TPACPI_MATCH_ANY, .ec = TPACPI_MATCH_ANY,
3223 .quirks = TPACPI_KEYMAP_IBM_GENERIC,
3224 },
3225 {
3226 .vendor = PCI_VENDOR_ID_LENOVO,
3227 .bios = TPACPI_MATCH_ANY, .ec = TPACPI_MATCH_ANY,
3228 .quirks = TPACPI_KEYMAP_LENOVO_GENERIC,
3229 },
3192 }; 3230 };
3193 3231
3194#define TPACPI_HOTKEY_MAP_LEN ARRAY_SIZE(ibm_keycode_map) 3232#define TPACPI_HOTKEY_MAP_SIZE sizeof(tpacpi_keymap_t)
3195#define TPACPI_HOTKEY_MAP_SIZE sizeof(ibm_keycode_map) 3233#define TPACPI_HOTKEY_MAP_TYPESIZE sizeof(tpacpi_keymap_t[0])
3196#define TPACPI_HOTKEY_MAP_TYPESIZE sizeof(ibm_keycode_map[0])
3197 3234
3198 int res, i; 3235 int res, i;
3199 int status; 3236 int status;
@@ -3202,6 +3239,7 @@ static int __init hotkey_init(struct ibm_init_struct *iibm)
3202 bool tabletsw_state = false; 3239 bool tabletsw_state = false;
3203 3240
3204 unsigned long quirks; 3241 unsigned long quirks;
3242 unsigned long keymap_id;
3205 3243
3206 vdbg_printk(TPACPI_DBG_INIT | TPACPI_DBG_HKEY, 3244 vdbg_printk(TPACPI_DBG_INIT | TPACPI_DBG_HKEY,
3207 "initializing hotkey subdriver\n"); 3245 "initializing hotkey subdriver\n");
@@ -3342,7 +3380,6 @@ static int __init hotkey_init(struct ibm_init_struct *iibm)
3342 goto err_exit; 3380 goto err_exit;
3343 3381
3344 /* Set up key map */ 3382 /* Set up key map */
3345
3346 hotkey_keycode_map = kmalloc(TPACPI_HOTKEY_MAP_SIZE, 3383 hotkey_keycode_map = kmalloc(TPACPI_HOTKEY_MAP_SIZE,
3347 GFP_KERNEL); 3384 GFP_KERNEL);
3348 if (!hotkey_keycode_map) { 3385 if (!hotkey_keycode_map) {
@@ -3352,17 +3389,14 @@ static int __init hotkey_init(struct ibm_init_struct *iibm)
3352 goto err_exit; 3389 goto err_exit;
3353 } 3390 }
3354 3391
3355 if (tpacpi_is_lenovo()) { 3392 keymap_id = tpacpi_check_quirks(tpacpi_keymap_qtable,
3356 dbg_printk(TPACPI_DBG_INIT | TPACPI_DBG_HKEY, 3393 ARRAY_SIZE(tpacpi_keymap_qtable));
3357 "using Lenovo default hot key map\n"); 3394 BUG_ON(keymap_id >= ARRAY_SIZE(tpacpi_keymaps));
3358 memcpy(hotkey_keycode_map, &lenovo_keycode_map, 3395 dbg_printk(TPACPI_DBG_INIT | TPACPI_DBG_HKEY,
3359 TPACPI_HOTKEY_MAP_SIZE); 3396 "using keymap number %lu\n", keymap_id);
3360 } else { 3397
3361 dbg_printk(TPACPI_DBG_INIT | TPACPI_DBG_HKEY, 3398 memcpy(hotkey_keycode_map, &tpacpi_keymaps[keymap_id],
3362 "using IBM default hot key map\n"); 3399 TPACPI_HOTKEY_MAP_SIZE);
3363 memcpy(hotkey_keycode_map, &ibm_keycode_map,
3364 TPACPI_HOTKEY_MAP_SIZE);
3365 }
3366 3400
3367 input_set_capability(tpacpi_inputdev, EV_MSC, MSC_SCAN); 3401 input_set_capability(tpacpi_inputdev, EV_MSC, MSC_SCAN);
3368 tpacpi_inputdev->keycodesize = TPACPI_HOTKEY_MAP_TYPESIZE; 3402 tpacpi_inputdev->keycodesize = TPACPI_HOTKEY_MAP_TYPESIZE;
@@ -3469,7 +3503,8 @@ static bool hotkey_notify_hotkey(const u32 hkey,
3469 *send_acpi_ev = true; 3503 *send_acpi_ev = true;
3470 *ignore_acpi_ev = false; 3504 *ignore_acpi_ev = false;
3471 3505
3472 if (scancode > 0 && scancode < 0x21) { 3506 /* HKEY event 0x1001 is scancode 0x00 */
3507 if (scancode > 0 && scancode <= TPACPI_HOTKEY_MAP_LEN) {
3473 scancode--; 3508 scancode--;
3474 if (!(hotkey_source_mask & (1 << scancode))) { 3509 if (!(hotkey_source_mask & (1 << scancode))) {
3475 tpacpi_input_send_key_masked(scancode); 3510 tpacpi_input_send_key_masked(scancode);
@@ -6080,13 +6115,18 @@ static struct backlight_ops ibm_backlight_data = {
6080 6115
6081/* --------------------------------------------------------------------- */ 6116/* --------------------------------------------------------------------- */
6082 6117
6118/*
6119 * Call _BCL method of video device. On some ThinkPads this will
6120 * switch the firmware to the ACPI brightness control mode.
6121 */
6122
6083static int __init tpacpi_query_bcl_levels(acpi_handle handle) 6123static int __init tpacpi_query_bcl_levels(acpi_handle handle)
6084{ 6124{
6085 struct acpi_buffer buffer = { ACPI_ALLOCATE_BUFFER, NULL }; 6125 struct acpi_buffer buffer = { ACPI_ALLOCATE_BUFFER, NULL };
6086 union acpi_object *obj; 6126 union acpi_object *obj;
6087 int rc; 6127 int rc;
6088 6128
6089 if (ACPI_SUCCESS(acpi_evaluate_object(handle, NULL, NULL, &buffer))) { 6129 if (ACPI_SUCCESS(acpi_evaluate_object(handle, "_BCL", NULL, &buffer))) {
6090 obj = (union acpi_object *)buffer.pointer; 6130 obj = (union acpi_object *)buffer.pointer;
6091 if (!obj || (obj->type != ACPI_TYPE_PACKAGE)) { 6131 if (!obj || (obj->type != ACPI_TYPE_PACKAGE)) {
6092 printk(TPACPI_ERR "Unknown _BCL data, " 6132 printk(TPACPI_ERR "Unknown _BCL data, "
@@ -6103,55 +6143,22 @@ static int __init tpacpi_query_bcl_levels(acpi_handle handle)
6103 return rc; 6143 return rc;
6104} 6144}
6105 6145
6106static acpi_status __init tpacpi_acpi_walk_find_bcl(acpi_handle handle,
6107 u32 lvl, void *context, void **rv)
6108{
6109 char name[ACPI_PATH_SEGMENT_LENGTH];
6110 struct acpi_buffer buffer = { sizeof(name), &name };
6111
6112 if (ACPI_SUCCESS(acpi_get_name(handle, ACPI_SINGLE_NAME, &buffer)) &&
6113 !strncmp("_BCL", name, sizeof(name) - 1)) {
6114 BUG_ON(!rv || !*rv);
6115 **(int **)rv = tpacpi_query_bcl_levels(handle);
6116 return AE_CTRL_TERMINATE;
6117 } else {
6118 return AE_OK;
6119 }
6120}
6121 6146
6122/* 6147/*
6123 * Returns 0 (no ACPI _BCL or _BCL invalid), or size of brightness map 6148 * Returns 0 (no ACPI _BCL or _BCL invalid), or size of brightness map
6124 */ 6149 */
6125static unsigned int __init tpacpi_check_std_acpi_brightness_support(void) 6150static unsigned int __init tpacpi_check_std_acpi_brightness_support(void)
6126{ 6151{
6127 int status; 6152 acpi_handle video_device;
6128 int bcl_levels = 0; 6153 int bcl_levels = 0;
6129 void *bcl_ptr = &bcl_levels;
6130
6131 if (!vid_handle)
6132 TPACPI_ACPIHANDLE_INIT(vid);
6133
6134 if (!vid_handle)
6135 return 0;
6136
6137 /*
6138 * Search for a _BCL method, and execute it. This is safe on all
6139 * ThinkPads, and as a side-effect, _BCL will place a Lenovo Vista
6140 * BIOS in ACPI backlight control mode. We do NOT have to care
6141 * about calling the _BCL method in an enabled video device, any
6142 * will do for our purposes.
6143 */
6144 6154
6145 status = acpi_walk_namespace(ACPI_TYPE_METHOD, vid_handle, 3, 6155 tpacpi_acpi_handle_locate("video", ACPI_VIDEO_HID, &video_device);
6146 tpacpi_acpi_walk_find_bcl, NULL, NULL, 6156 if (video_device)
6147 &bcl_ptr); 6157 bcl_levels = tpacpi_query_bcl_levels(video_device);
6148 6158
6149 if (ACPI_SUCCESS(status) && bcl_levels > 2) { 6159 tp_features.bright_acpimode = (bcl_levels > 0);
6150 tp_features.bright_acpimode = 1;
6151 return bcl_levels - 2;
6152 }
6153 6160
6154 return 0; 6161 return (bcl_levels > 2) ? (bcl_levels - 2) : 0;
6155} 6162}
6156 6163
6157/* 6164/*
@@ -6244,28 +6251,6 @@ static int __init brightness_init(struct ibm_init_struct *iibm)
6244 if (tp_features.bright_unkfw) 6251 if (tp_features.bright_unkfw)
6245 return 1; 6252 return 1;
6246 6253
6247 if (tp_features.bright_acpimode) {
6248 if (acpi_video_backlight_support()) {
6249 if (brightness_enable > 1) {
6250 printk(TPACPI_NOTICE
6251 "Standard ACPI backlight interface "
6252 "available, not loading native one.\n");
6253 return 1;
6254 } else if (brightness_enable == 1) {
6255 printk(TPACPI_NOTICE
6256 "Backlight control force enabled, even if standard "
6257 "ACPI backlight interface is available\n");
6258 }
6259 } else {
6260 if (brightness_enable > 1) {
6261 printk(TPACPI_NOTICE
6262 "Standard ACPI backlight interface not "
6263 "available, thinkpad_acpi native "
6264 "brightness control enabled\n");
6265 }
6266 }
6267 }
6268
6269 if (!brightness_enable) { 6254 if (!brightness_enable) {
6270 dbg_printk(TPACPI_DBG_INIT | TPACPI_DBG_BRGHT, 6255 dbg_printk(TPACPI_DBG_INIT | TPACPI_DBG_BRGHT,
6271 "brightness support disabled by " 6256 "brightness support disabled by "
@@ -6273,6 +6258,26 @@ static int __init brightness_init(struct ibm_init_struct *iibm)
6273 return 1; 6258 return 1;
6274 } 6259 }
6275 6260
6261 if (acpi_video_backlight_support()) {
6262 if (brightness_enable > 1) {
6263 printk(TPACPI_INFO
6264 "Standard ACPI backlight interface "
6265 "available, not loading native one.\n");
6266 return 1;
6267 } else if (brightness_enable == 1) {
6268 printk(TPACPI_WARN
6269 "Cannot enable backlight brightness support, "
6270 "ACPI is already handling it. Refer to the "
6271 "acpi_backlight kernel parameter\n");
6272 return 1;
6273 }
6274 } else if (tp_features.bright_acpimode && brightness_enable > 1) {
6275 printk(TPACPI_NOTICE
6276 "Standard ACPI backlight interface not "
6277 "available, thinkpad_acpi native "
6278 "brightness control enabled\n");
6279 }
6280
6276 /* 6281 /*
6277 * Check for module parameter bogosity, note that we 6282 * Check for module parameter bogosity, note that we
6278 * init brightness_mode to TPACPI_BRGHT_MODE_MAX in order to be 6283 * init brightness_mode to TPACPI_BRGHT_MODE_MAX in order to be