1
0
Fork 0

Merge branch 'thinkpad' into release

hifive-unleashed-5.1
Len Brown 2009-09-19 01:06:16 -04:00
commit 596fb7ae46
2 changed files with 315 additions and 74 deletions

View File

@ -219,7 +219,7 @@ The following commands can be written to the /proc/acpi/ibm/hotkey file:
echo 0xffffffff > /proc/acpi/ibm/hotkey -- enable all hot keys
echo 0 > /proc/acpi/ibm/hotkey -- disable all possible hot keys
... any other 8-hex-digit mask ...
echo reset > /proc/acpi/ibm/hotkey -- restore the original mask
echo reset > /proc/acpi/ibm/hotkey -- restore the recommended mask
The following commands have been deprecated and will cause the kernel
to log a warning:
@ -240,9 +240,13 @@ sysfs notes:
Returns 0.
hotkey_bios_mask:
DEPRECATED, DON'T USE, WILL BE REMOVED IN THE FUTURE.
Returns the hot keys mask when thinkpad-acpi was loaded.
Upon module unload, the hot keys mask will be restored
to this value.
to this value. This is always 0x80c, because those are
the hotkeys that were supported by ancient firmware
without mask support.
hotkey_enable:
DEPRECATED, WILL BE REMOVED SOON.

View File

@ -1601,6 +1601,196 @@ static void tpacpi_remove_driver_attributes(struct device_driver *drv)
#endif
}
/*************************************************************************
* Firmware Data
*/
/*
* Table of recommended minimum BIOS versions
*
* Reasons for listing:
* 1. Stable BIOS, listed because the unknown ammount of
* bugs and bad ACPI behaviour on older versions
*
* 2. BIOS or EC fw with known bugs that trigger on Linux
*
* 3. BIOS with known reduced functionality in older versions
*
* We recommend the latest BIOS and EC version.
* We only support the latest BIOS and EC fw version as a rule.
*
* Sources: IBM ThinkPad Public Web Documents (update changelogs),
* Information from users in ThinkWiki
*
* WARNING: we use this table also to detect that the machine is
* a ThinkPad in some cases, so don't remove entries lightly.
*/
#define TPV_Q(__v, __id1, __id2, __bv1, __bv2) \
{ .vendor = (__v), \
.bios = TPID(__id1, __id2), \
.ec = TPACPI_MATCH_ANY, \
.quirks = TPACPI_MATCH_ANY << 16 \
| (__bv1) << 8 | (__bv2) }
#define TPV_Q_X(__v, __bid1, __bid2, __bv1, __bv2, \
__eid1, __eid2, __ev1, __ev2) \
{ .vendor = (__v), \
.bios = TPID(__bid1, __bid2), \
.ec = TPID(__eid1, __eid2), \
.quirks = (__ev1) << 24 | (__ev2) << 16 \
| (__bv1) << 8 | (__bv2) }
#define TPV_QI0(__id1, __id2, __bv1, __bv2) \
TPV_Q(PCI_VENDOR_ID_IBM, __id1, __id2, __bv1, __bv2)
#define TPV_QI1(__id1, __id2, __bv1, __bv2, __ev1, __ev2) \
TPV_Q_X(PCI_VENDOR_ID_IBM, __id1, __id2, \
__bv1, __bv2, __id1, __id2, __ev1, __ev2)
#define TPV_QI2(__bid1, __bid2, __bv1, __bv2, \
__eid1, __eid2, __ev1, __ev2) \
TPV_Q_X(PCI_VENDOR_ID_IBM, __bid1, __bid2, \
__bv1, __bv2, __eid1, __eid2, __ev1, __ev2)
#define TPV_QL0(__id1, __id2, __bv1, __bv2) \
TPV_Q(PCI_VENDOR_ID_LENOVO, __id1, __id2, __bv1, __bv2)
#define TPV_QL1(__id1, __id2, __bv1, __bv2, __ev1, __ev2) \
TPV_Q_X(PCI_VENDOR_ID_LENOVO, __id1, __id2, \
__bv1, __bv2, __id1, __id2, __ev1, __ev2)
#define TPV_QL2(__bid1, __bid2, __bv1, __bv2, \
__eid1, __eid2, __ev1, __ev2) \
TPV_Q_X(PCI_VENDOR_ID_LENOVO, __bid1, __bid2, \
__bv1, __bv2, __eid1, __eid2, __ev1, __ev2)
static const struct tpacpi_quirk tpacpi_bios_version_qtable[] __initconst = {
/* Numeric models ------------------ */
/* FW MODEL BIOS VERS */
TPV_QI0('I', 'M', '6', '5'), /* 570 */
TPV_QI0('I', 'U', '2', '6'), /* 570E */
TPV_QI0('I', 'B', '5', '4'), /* 600 */
TPV_QI0('I', 'H', '4', '7'), /* 600E */
TPV_QI0('I', 'N', '3', '6'), /* 600E */
TPV_QI0('I', 'T', '5', '5'), /* 600X */
TPV_QI0('I', 'D', '4', '8'), /* 770, 770E, 770ED */
TPV_QI0('I', 'I', '4', '2'), /* 770X */
TPV_QI0('I', 'O', '2', '3'), /* 770Z */
/* A-series ------------------------- */
/* FW MODEL BIOS VERS EC VERS */
TPV_QI0('I', 'W', '5', '9'), /* A20m */
TPV_QI0('I', 'V', '6', '9'), /* A20p */
TPV_QI0('1', '0', '2', '6'), /* A21e, A22e */
TPV_QI0('K', 'U', '3', '6'), /* A21e */
TPV_QI0('K', 'X', '3', '6'), /* A21m, A22m */
TPV_QI0('K', 'Y', '3', '8'), /* A21p, A22p */
TPV_QI0('1', 'B', '1', '7'), /* A22e */
TPV_QI0('1', '3', '2', '0'), /* A22m */
TPV_QI0('1', 'E', '7', '3'), /* A30/p (0) */
TPV_QI1('1', 'G', '4', '1', '1', '7'), /* A31/p (0) */
TPV_QI1('1', 'N', '1', '6', '0', '7'), /* A31/p (0) */
/* G-series ------------------------- */
/* FW MODEL BIOS VERS */
TPV_QI0('1', 'T', 'A', '6'), /* G40 */
TPV_QI0('1', 'X', '5', '7'), /* G41 */
/* R-series, T-series --------------- */
/* FW MODEL BIOS VERS EC VERS */
TPV_QI0('1', 'C', 'F', '0'), /* R30 */
TPV_QI0('1', 'F', 'F', '1'), /* R31 */
TPV_QI0('1', 'M', '9', '7'), /* R32 */
TPV_QI0('1', 'O', '6', '1'), /* R40 */
TPV_QI0('1', 'P', '6', '5'), /* R40 */
TPV_QI0('1', 'S', '7', '0'), /* R40e */
TPV_QI1('1', 'R', 'D', 'R', '7', '1'), /* R50/p, R51,
T40/p, T41/p, T42/p (1) */
TPV_QI1('1', 'V', '7', '1', '2', '8'), /* R50e, R51 (1) */
TPV_QI1('7', '8', '7', '1', '0', '6'), /* R51e (1) */
TPV_QI1('7', '6', '6', '9', '1', '6'), /* R52 (1) */
TPV_QI1('7', '0', '6', '9', '2', '8'), /* R52, T43 (1) */
TPV_QI0('I', 'Y', '6', '1'), /* T20 */
TPV_QI0('K', 'Z', '3', '4'), /* T21 */
TPV_QI0('1', '6', '3', '2'), /* T22 */
TPV_QI1('1', 'A', '6', '4', '2', '3'), /* T23 (0) */
TPV_QI1('1', 'I', '7', '1', '2', '0'), /* T30 (0) */
TPV_QI1('1', 'Y', '6', '5', '2', '9'), /* T43/p (1) */
TPV_QL1('7', '9', 'E', '3', '5', '0'), /* T60/p */
TPV_QL1('7', 'C', 'D', '2', '2', '2'), /* R60, R60i */
TPV_QL0('7', 'E', 'D', '0'), /* R60e, R60i */
/* BIOS FW BIOS VERS EC FW EC VERS */
TPV_QI2('1', 'W', '9', '0', '1', 'V', '2', '8'), /* R50e (1) */
TPV_QL2('7', 'I', '3', '4', '7', '9', '5', '0'), /* T60/p wide */
/* X-series ------------------------- */
/* FW MODEL BIOS VERS EC VERS */
TPV_QI0('I', 'Z', '9', 'D'), /* X20, X21 */
TPV_QI0('1', 'D', '7', '0'), /* X22, X23, X24 */
TPV_QI1('1', 'K', '4', '8', '1', '8'), /* X30 (0) */
TPV_QI1('1', 'Q', '9', '7', '2', '3'), /* X31, X32 (0) */
TPV_QI1('1', 'U', 'D', '3', 'B', '2'), /* X40 (0) */
TPV_QI1('7', '4', '6', '4', '2', '7'), /* X41 (0) */
TPV_QI1('7', '5', '6', '0', '2', '0'), /* X41t (0) */
TPV_QL0('7', 'B', 'D', '7'), /* X60/s */
TPV_QL0('7', 'J', '3', '0'), /* X60t */
/* (0) - older versions lack DMI EC fw string and functionality */
/* (1) - older versions known to lack functionality */
};
#undef TPV_QL1
#undef TPV_QL0
#undef TPV_QI2
#undef TPV_QI1
#undef TPV_QI0
#undef TPV_Q_X
#undef TPV_Q
static void __init tpacpi_check_outdated_fw(void)
{
unsigned long fwvers;
u16 ec_version, bios_version;
fwvers = tpacpi_check_quirks(tpacpi_bios_version_qtable,
ARRAY_SIZE(tpacpi_bios_version_qtable));
if (!fwvers)
return;
bios_version = fwvers & 0xffffU;
ec_version = (fwvers >> 16) & 0xffffU;
/* note that unknown versions are set to 0x0000 and we use that */
if ((bios_version > thinkpad_id.bios_release) ||
(ec_version > thinkpad_id.ec_release &&
ec_version != TPACPI_MATCH_ANY)) {
/*
* The changelogs would let us track down the exact
* reason, but it is just too much of a pain to track
* it. We only list BIOSes that are either really
* broken, or really stable to begin with, so it is
* best if the user upgrades the firmware anyway.
*/
printk(TPACPI_WARN
"WARNING: Outdated ThinkPad BIOS/EC firmware\n");
printk(TPACPI_WARN
"WARNING: This firmware may be missing critical bug "
"fixes and/or important features\n");
}
}
static bool __init tpacpi_is_fw_known(void)
{
return tpacpi_check_quirks(tpacpi_bios_version_qtable,
ARRAY_SIZE(tpacpi_bios_version_qtable)) != 0;
}
/****************************************************************************
****************************************************************************
*
@ -1634,6 +1824,7 @@ static int __init thinkpad_acpi_driver_init(struct ibm_init_struct *iibm)
(thinkpad_id.nummodel_str) ?
thinkpad_id.nummodel_str : "unknown");
tpacpi_check_outdated_fw();
return 0;
}
@ -1731,16 +1922,42 @@ struct tp_nvram_state {
u8 volume_level;
};
/* kthread for the hotkey poller */
static struct task_struct *tpacpi_hotkey_task;
static u32 hotkey_source_mask; /* bit mask 0=ACPI,1=NVRAM */
static int hotkey_poll_freq = 10; /* Hz */
/* Acquired while the poller kthread is running, use to sync start/stop */
static struct mutex hotkey_thread_mutex;
/*
* Acquire mutex to write poller control variables.
* Increment hotkey_config_change when changing them.
*
* See HOTKEY_CONFIG_CRITICAL_START/HOTKEY_CONFIG_CRITICAL_END
*/
static struct mutex hotkey_thread_data_mutex;
static unsigned int hotkey_config_change;
/*
* hotkey poller control variables
*
* Must be atomic or readers will also need to acquire mutex
*/
static u32 hotkey_source_mask; /* bit mask 0=ACPI,1=NVRAM */
static unsigned int hotkey_poll_freq = 10; /* Hz */
#define HOTKEY_CONFIG_CRITICAL_START \
do { \
mutex_lock(&hotkey_thread_data_mutex); \
hotkey_config_change++; \
} while (0);
#define HOTKEY_CONFIG_CRITICAL_END \
mutex_unlock(&hotkey_thread_data_mutex);
#else /* CONFIG_THINKPAD_ACPI_HOTKEY_POLL */
#define hotkey_source_mask 0U
#define HOTKEY_CONFIG_CRITICAL_START
#define HOTKEY_CONFIG_CRITICAL_END
#endif /* CONFIG_THINKPAD_ACPI_HOTKEY_POLL */
@ -1765,19 +1982,6 @@ static u16 *hotkey_keycode_map;
static struct attribute_set *hotkey_dev_attributes;
#ifdef CONFIG_THINKPAD_ACPI_HOTKEY_POLL
#define HOTKEY_CONFIG_CRITICAL_START \
do { \
mutex_lock(&hotkey_thread_data_mutex); \
hotkey_config_change++; \
} while (0);
#define HOTKEY_CONFIG_CRITICAL_END \
mutex_unlock(&hotkey_thread_data_mutex);
#else
#define HOTKEY_CONFIG_CRITICAL_START
#define HOTKEY_CONFIG_CRITICAL_END
#endif /* CONFIG_THINKPAD_ACPI_HOTKEY_POLL */
/* HKEY.MHKG() return bits */
#define TP_HOTKEY_TABLET_MASK (1 << 3)
@ -1822,7 +2026,9 @@ static int hotkey_mask_get(void)
if (!acpi_evalf(hkey_handle, &m, "DHKN", "d"))
return -EIO;
}
HOTKEY_CONFIG_CRITICAL_START
hotkey_mask = m | (hotkey_source_mask & hotkey_mask);
HOTKEY_CONFIG_CRITICAL_END
return 0;
}
@ -2075,6 +2281,7 @@ static int hotkey_kthread(void *data)
unsigned int si, so;
unsigned long t;
unsigned int change_detector, must_reset;
unsigned int poll_freq;
mutex_lock(&hotkey_thread_mutex);
@ -2091,12 +2298,17 @@ static int hotkey_kthread(void *data)
mutex_lock(&hotkey_thread_data_mutex);
change_detector = hotkey_config_change;
mask = hotkey_source_mask & hotkey_mask;
poll_freq = hotkey_poll_freq;
mutex_unlock(&hotkey_thread_data_mutex);
hotkey_read_nvram(&s[so], mask);
while (!kthread_should_stop() && hotkey_poll_freq) {
if (t == 0)
t = 1000/hotkey_poll_freq;
while (!kthread_should_stop()) {
if (t == 0) {
if (likely(poll_freq))
t = 1000/poll_freq;
else
t = 100; /* should never happen... */
}
t = msleep_interruptible(t);
if (unlikely(kthread_should_stop()))
break;
@ -2112,6 +2324,7 @@ static int hotkey_kthread(void *data)
change_detector = hotkey_config_change;
}
mask = hotkey_source_mask & hotkey_mask;
poll_freq = hotkey_poll_freq;
mutex_unlock(&hotkey_thread_data_mutex);
if (likely(mask)) {
@ -2131,6 +2344,7 @@ exit:
return 0;
}
/* call with hotkey_mutex held */
static void hotkey_poll_stop_sync(void)
{
if (tpacpi_hotkey_task) {
@ -2147,10 +2361,11 @@ static void hotkey_poll_stop_sync(void)
}
/* call with hotkey_mutex held */
static void hotkey_poll_setup(int may_warn)
static void hotkey_poll_setup(bool may_warn)
{
if ((hotkey_source_mask & hotkey_mask) != 0 &&
hotkey_poll_freq > 0 &&
u32 hotkeys_to_poll = hotkey_source_mask & hotkey_mask;
if (hotkeys_to_poll != 0 && hotkey_poll_freq > 0 &&
(tpacpi_inputdev->users > 0 || hotkey_report_mode < 2)) {
if (!tpacpi_hotkey_task) {
tpacpi_hotkey_task = kthread_run(hotkey_kthread,
@ -2164,26 +2379,37 @@ static void hotkey_poll_setup(int may_warn)
}
} else {
hotkey_poll_stop_sync();
if (may_warn &&
hotkey_source_mask != 0 && hotkey_poll_freq == 0) {
if (may_warn && hotkeys_to_poll != 0 &&
hotkey_poll_freq == 0) {
printk(TPACPI_NOTICE
"hot keys 0x%08x require polling, "
"which is currently disabled\n",
hotkey_source_mask);
hotkeys_to_poll);
}
}
}
static void hotkey_poll_setup_safe(int may_warn)
static void hotkey_poll_setup_safe(bool may_warn)
{
mutex_lock(&hotkey_mutex);
hotkey_poll_setup(may_warn);
mutex_unlock(&hotkey_mutex);
}
/* call with hotkey_mutex held */
static void hotkey_poll_set_freq(unsigned int freq)
{
if (!freq)
hotkey_poll_stop_sync();
HOTKEY_CONFIG_CRITICAL_START
hotkey_poll_freq = freq;
HOTKEY_CONFIG_CRITICAL_END
}
#else /* CONFIG_THINKPAD_ACPI_HOTKEY_POLL */
static void hotkey_poll_setup_safe(int __unused)
static void hotkey_poll_setup_safe(bool __unused)
{
}
@ -2201,7 +2427,7 @@ static int hotkey_inputdev_open(struct input_dev *dev)
case TPACPI_LIFE_EXITING:
return -EBUSY;
case TPACPI_LIFE_RUNNING:
hotkey_poll_setup_safe(0);
hotkey_poll_setup_safe(false);
return 0;
}
@ -2214,7 +2440,7 @@ static void hotkey_inputdev_close(struct input_dev *dev)
{
/* disable hotkey polling when possible */
if (tpacpi_lifecycle == TPACPI_LIFE_RUNNING)
hotkey_poll_setup_safe(0);
hotkey_poll_setup_safe(false);
}
/* sysfs hotkey enable ------------------------------------------------- */
@ -2288,7 +2514,7 @@ static ssize_t hotkey_mask_store(struct device *dev,
res = hotkey_mask_set(t);
#ifdef CONFIG_THINKPAD_ACPI_HOTKEY_POLL
hotkey_poll_setup(1);
hotkey_poll_setup(true);
#endif
mutex_unlock(&hotkey_mutex);
@ -2318,6 +2544,8 @@ static ssize_t hotkey_bios_mask_show(struct device *dev,
struct device_attribute *attr,
char *buf)
{
printk_deprecated_attribute("hotkey_bios_mask",
"This attribute is useless.");
return snprintf(buf, PAGE_SIZE, "0x%08x\n", hotkey_orig_mask);
}
@ -2377,7 +2605,8 @@ static ssize_t hotkey_source_mask_store(struct device *dev,
hotkey_source_mask = t;
HOTKEY_CONFIG_CRITICAL_END
hotkey_poll_setup(1);
hotkey_poll_setup(true);
hotkey_mask_set(hotkey_mask);
mutex_unlock(&hotkey_mutex);
@ -2410,9 +2639,9 @@ static ssize_t hotkey_poll_freq_store(struct device *dev,
if (mutex_lock_killable(&hotkey_mutex))
return -ERESTARTSYS;
hotkey_poll_freq = t;
hotkey_poll_set_freq(t);
hotkey_poll_setup(true);
hotkey_poll_setup(1);
mutex_unlock(&hotkey_mutex);
tpacpi_disclose_usertask("hotkey_poll_freq", "set to %lu\n", t);
@ -2603,7 +2832,9 @@ static void tpacpi_send_radiosw_update(void)
static void hotkey_exit(void)
{
#ifdef CONFIG_THINKPAD_ACPI_HOTKEY_POLL
mutex_lock(&hotkey_mutex);
hotkey_poll_stop_sync();
mutex_unlock(&hotkey_mutex);
#endif
if (hotkey_dev_attributes)
@ -2623,6 +2854,15 @@ static void hotkey_exit(void)
}
}
static void __init hotkey_unmap(const unsigned int scancode)
{
if (hotkey_keycode_map[scancode] != KEY_RESERVED) {
clear_bit(hotkey_keycode_map[scancode],
tpacpi_inputdev->keybit);
hotkey_keycode_map[scancode] = KEY_RESERVED;
}
}
static int __init hotkey_init(struct ibm_init_struct *iibm)
{
/* Requirements for changing the default keymaps:
@ -2701,11 +2941,11 @@ static int __init hotkey_init(struct ibm_init_struct *iibm)
KEY_UNKNOWN, /* 0x0D: FN+INSERT */
KEY_UNKNOWN, /* 0x0E: FN+DELETE */
/* These either have to go through ACPI video, or
* act like in the IBM ThinkPads, so don't ever
* enable them by default */
KEY_RESERVED, /* 0x0F: FN+HOME (brightness up) */
KEY_RESERVED, /* 0x10: FN+END (brightness down) */
/* These should be enabled --only-- when ACPI video
* is disabled (i.e. in "vendor" mode), and are handled
* in a special way by the init code */
KEY_BRIGHTNESSUP, /* 0x0F: FN+HOME (brightness up) */
KEY_BRIGHTNESSDOWN, /* 0x10: FN+END (brightness down) */
KEY_RESERVED, /* 0x11: FN+PGUP (thinklight toggle) */
@ -2831,19 +3071,6 @@ static int __init hotkey_init(struct ibm_init_struct *iibm)
goto err_exit;
}
#ifdef CONFIG_THINKPAD_ACPI_HOTKEY_POLL
if (tp_features.hotkey_mask) {
hotkey_source_mask = TPACPI_HKEY_NVRAM_GOOD_MASK
& ~hotkey_all_mask;
} else {
hotkey_source_mask = TPACPI_HKEY_NVRAM_GOOD_MASK;
}
vdbg_printk(TPACPI_DBG_INIT | TPACPI_DBG_HKEY,
"hotkey source mask 0x%08x, polling freq %d\n",
hotkey_source_mask, hotkey_poll_freq);
#endif
#ifdef CONFIG_THINKPAD_ACPI_DEBUGFACILITIES
if (dbg_wlswemul) {
tp_features.hotkey_wlsw = 1;
@ -2944,17 +3171,31 @@ static int __init hotkey_init(struct ibm_init_struct *iibm)
"Disabling thinkpad-acpi brightness events "
"by default...\n");
/* The hotkey_reserved_mask change below is not
* necessary while the keys are at KEY_RESERVED in the
* default map, but better safe than sorry, leave it
* here as a marker of what we have to do, especially
* when we finally become able to set this at runtime
* on response to X.org requests */
/* Disable brightness up/down on Lenovo thinkpads when
* ACPI is handling them, otherwise it is plain impossible
* for userspace to do something even remotely sane */
hotkey_reserved_mask |=
(1 << TP_ACPI_HOTKEYSCAN_FNHOME)
| (1 << TP_ACPI_HOTKEYSCAN_FNEND);
hotkey_unmap(TP_ACPI_HOTKEYSCAN_FNHOME);
hotkey_unmap(TP_ACPI_HOTKEYSCAN_FNEND);
}
#ifdef CONFIG_THINKPAD_ACPI_HOTKEY_POLL
if (tp_features.hotkey_mask) {
hotkey_source_mask = TPACPI_HKEY_NVRAM_GOOD_MASK
& ~hotkey_all_mask
& ~hotkey_reserved_mask;
} else {
hotkey_source_mask = TPACPI_HKEY_NVRAM_GOOD_MASK
& ~hotkey_reserved_mask;
}
vdbg_printk(TPACPI_DBG_INIT | TPACPI_DBG_HKEY,
"hotkey source mask 0x%08x, polling freq %u\n",
hotkey_source_mask, hotkey_poll_freq);
#endif
dbg_printk(TPACPI_DBG_INIT | TPACPI_DBG_HKEY,
"enabling firmware HKEY event interface...\n");
res = hotkey_status_set(true);
@ -2978,7 +3219,7 @@ static int __init hotkey_init(struct ibm_init_struct *iibm)
tpacpi_inputdev->open = &hotkey_inputdev_open;
tpacpi_inputdev->close = &hotkey_inputdev_close;
hotkey_poll_setup_safe(1);
hotkey_poll_setup_safe(true);
tpacpi_send_radiosw_update();
tpacpi_input_send_tabletsw();
@ -3266,7 +3507,7 @@ static void hotkey_resume(void)
hotkey_tablet_mode_notify_change();
hotkey_wakeup_reason_notify_change();
hotkey_wakeup_hotunplug_complete_notify_change();
hotkey_poll_setup_safe(0);
hotkey_poll_setup_safe(false);
}
/* procfs -------------------------------------------------------------- */
@ -3338,7 +3579,8 @@ static int hotkey_write(char *buf)
hotkey_enabledisable_warn(0);
res = -EPERM;
} else if (strlencmp(cmd, "reset") == 0) {
mask = hotkey_orig_mask;
mask = (hotkey_all_mask | hotkey_source_mask)
& ~hotkey_reserved_mask;
} else if (sscanf(cmd, "0x%x", &mask) == 1) {
/* mask set */
} else if (sscanf(cmd, "%x", &mask) == 1) {
@ -5655,16 +5897,16 @@ static const struct tpacpi_quirk brightness_quirk_table[] __initconst = {
/* Models with ATI GPUs known to require ECNVRAM mode */
TPACPI_Q_IBM('1', 'Y', TPACPI_BRGHT_Q_EC), /* T43/p ATI */
/* Models with ATI GPUs (waiting confirmation) */
TPACPI_Q_IBM('1', 'R', TPACPI_BRGHT_Q_ASK|TPACPI_BRGHT_Q_EC),
/* Models with ATI GPUs that can use ECNVRAM */
TPACPI_Q_IBM('1', 'R', TPACPI_BRGHT_Q_EC),
TPACPI_Q_IBM('1', 'Q', TPACPI_BRGHT_Q_ASK|TPACPI_BRGHT_Q_EC),
TPACPI_Q_IBM('7', '6', TPACPI_BRGHT_Q_ASK|TPACPI_BRGHT_Q_EC),
TPACPI_Q_IBM('7', '8', TPACPI_BRGHT_Q_ASK|TPACPI_BRGHT_Q_EC),
/* Models with Intel Extreme Graphics 2 (waiting confirmation) */
/* Models with Intel Extreme Graphics 2 */
TPACPI_Q_IBM('1', 'U', TPACPI_BRGHT_Q_NOEC),
TPACPI_Q_IBM('1', 'V', TPACPI_BRGHT_Q_ASK|TPACPI_BRGHT_Q_NOEC),
TPACPI_Q_IBM('1', 'W', TPACPI_BRGHT_Q_ASK|TPACPI_BRGHT_Q_NOEC),
TPACPI_Q_IBM('1', 'U', TPACPI_BRGHT_Q_ASK|TPACPI_BRGHT_Q_NOEC),
/* Models with Intel GMA900 */
TPACPI_Q_IBM('7', '0', TPACPI_BRGHT_Q_NOEC), /* T43, R52 */
@ -7524,9 +7766,11 @@ static int __init probe_for_thinkpad(void)
/*
* Non-ancient models have better DMI tagging, but very old models
* don't.
* don't. tpacpi_is_fw_known() is a cheat to help in that case.
*/
is_thinkpad = (thinkpad_id.model_str != NULL);
is_thinkpad = (thinkpad_id.model_str != NULL) ||
(thinkpad_id.ec_model != 0) ||
tpacpi_is_fw_known();
/* ec is required because many other handles are relative to it */
TPACPI_ACPIHANDLE_INIT(ec);
@ -7537,13 +7781,6 @@ static int __init probe_for_thinkpad(void)
return -ENODEV;
}
/*
* Risks a regression on very old machines, but reduces potential
* false positives a damn great deal
*/
if (!is_thinkpad)
is_thinkpad = (thinkpad_id.vendor == PCI_VENDOR_ID_IBM);
if (!is_thinkpad && !force_load)
return -ENODEV;