diff options
Diffstat (limited to 'drivers/platform/x86/thinkpad_acpi.c')
-rw-r--r-- | drivers/platform/x86/thinkpad_acpi.c | 171 |
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 | ||
1916 | enum { /* Keys/events available through NVRAM polling */ | 1927 | enum { /* 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 | ||
3096 | typedef u16 tpacpi_keymap_t[TPACPI_HOTKEY_MAP_LEN]; | ||
3097 | |||
3085 | static int __init hotkey_init(struct ibm_init_struct *iibm) | 3098 | static 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 | |||
6083 | static int __init tpacpi_query_bcl_levels(acpi_handle handle) | 6123 | static 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 | ||
6106 | static 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 | */ |
6125 | static unsigned int __init tpacpi_check_std_acpi_brightness_support(void) | 6150 | static 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 |