提交 26822eeb 编写于 作者: L Linus Torvalds

Merge branch 'for_linus' of...

Merge branch 'for_linus' of git://git.kernel.org/pub/scm/linux/kernel/git/mjg59/platform-drivers-x86

* 'for_linus' of git://git.kernel.org/pub/scm/linux/kernel/git/mjg59/platform-drivers-x86:
  eeepc-laptop: Use ACPI handle to identify rfkill port
  [PATCH] sony-laptop: limit brightness range to DSDT provided ones
  sony-laptop: report failures on setting LCD brightness
  thinkpad-acpi: module autoloading for newer Lenovo ThinkPads.
...@@ -585,8 +585,9 @@ static bool eeepc_wlan_rfkill_blocked(struct eeepc_laptop *eeepc) ...@@ -585,8 +585,9 @@ static bool eeepc_wlan_rfkill_blocked(struct eeepc_laptop *eeepc)
return true; return true;
} }
static void eeepc_rfkill_hotplug(struct eeepc_laptop *eeepc) static void eeepc_rfkill_hotplug(struct eeepc_laptop *eeepc, acpi_handle handle)
{ {
struct pci_dev *port;
struct pci_dev *dev; struct pci_dev *dev;
struct pci_bus *bus; struct pci_bus *bus;
bool blocked = eeepc_wlan_rfkill_blocked(eeepc); bool blocked = eeepc_wlan_rfkill_blocked(eeepc);
...@@ -599,9 +600,16 @@ static void eeepc_rfkill_hotplug(struct eeepc_laptop *eeepc) ...@@ -599,9 +600,16 @@ static void eeepc_rfkill_hotplug(struct eeepc_laptop *eeepc)
mutex_lock(&eeepc->hotplug_lock); mutex_lock(&eeepc->hotplug_lock);
if (eeepc->hotplug_slot) { if (eeepc->hotplug_slot) {
bus = pci_find_bus(0, 1); port = acpi_get_pci_dev(handle);
if (!port) {
pr_warning("Unable to find port\n");
goto out_unlock;
}
bus = port->subordinate;
if (!bus) { if (!bus) {
pr_warning("Unable to find PCI bus 1?\n"); pr_warning("Unable to find PCI bus?\n");
goto out_unlock; goto out_unlock;
} }
...@@ -609,6 +617,7 @@ static void eeepc_rfkill_hotplug(struct eeepc_laptop *eeepc) ...@@ -609,6 +617,7 @@ static void eeepc_rfkill_hotplug(struct eeepc_laptop *eeepc)
pr_err("Unable to read PCI config space?\n"); pr_err("Unable to read PCI config space?\n");
goto out_unlock; goto out_unlock;
} }
absent = (l == 0xffffffff); absent = (l == 0xffffffff);
if (blocked != absent) { if (blocked != absent) {
...@@ -647,6 +656,17 @@ static void eeepc_rfkill_hotplug(struct eeepc_laptop *eeepc) ...@@ -647,6 +656,17 @@ static void eeepc_rfkill_hotplug(struct eeepc_laptop *eeepc)
mutex_unlock(&eeepc->hotplug_lock); mutex_unlock(&eeepc->hotplug_lock);
} }
static void eeepc_rfkill_hotplug_update(struct eeepc_laptop *eeepc, char *node)
{
acpi_status status = AE_OK;
acpi_handle handle;
status = acpi_get_handle(NULL, node, &handle);
if (ACPI_SUCCESS(status))
eeepc_rfkill_hotplug(eeepc, handle);
}
static void eeepc_rfkill_notify(acpi_handle handle, u32 event, void *data) static void eeepc_rfkill_notify(acpi_handle handle, u32 event, void *data)
{ {
struct eeepc_laptop *eeepc = data; struct eeepc_laptop *eeepc = data;
...@@ -654,7 +674,7 @@ static void eeepc_rfkill_notify(acpi_handle handle, u32 event, void *data) ...@@ -654,7 +674,7 @@ static void eeepc_rfkill_notify(acpi_handle handle, u32 event, void *data)
if (event != ACPI_NOTIFY_BUS_CHECK) if (event != ACPI_NOTIFY_BUS_CHECK)
return; return;
eeepc_rfkill_hotplug(eeepc); eeepc_rfkill_hotplug(eeepc, handle);
} }
static int eeepc_register_rfkill_notifier(struct eeepc_laptop *eeepc, static int eeepc_register_rfkill_notifier(struct eeepc_laptop *eeepc,
...@@ -672,6 +692,11 @@ static int eeepc_register_rfkill_notifier(struct eeepc_laptop *eeepc, ...@@ -672,6 +692,11 @@ static int eeepc_register_rfkill_notifier(struct eeepc_laptop *eeepc,
eeepc); eeepc);
if (ACPI_FAILURE(status)) if (ACPI_FAILURE(status))
pr_warning("Failed to register notify on %s\n", node); pr_warning("Failed to register notify on %s\n", node);
/*
* Refresh pci hotplug in case the rfkill state was
* changed during setup.
*/
eeepc_rfkill_hotplug(eeepc, handle);
} else } else
return -ENODEV; return -ENODEV;
...@@ -693,6 +718,12 @@ static void eeepc_unregister_rfkill_notifier(struct eeepc_laptop *eeepc, ...@@ -693,6 +718,12 @@ static void eeepc_unregister_rfkill_notifier(struct eeepc_laptop *eeepc,
if (ACPI_FAILURE(status)) if (ACPI_FAILURE(status))
pr_err("Error removing rfkill notify handler %s\n", pr_err("Error removing rfkill notify handler %s\n",
node); node);
/*
* Refresh pci hotplug in case the rfkill
* state was changed after
* eeepc_unregister_rfkill_notifier()
*/
eeepc_rfkill_hotplug(eeepc, handle);
} }
} }
...@@ -816,11 +847,7 @@ static void eeepc_rfkill_exit(struct eeepc_laptop *eeepc) ...@@ -816,11 +847,7 @@ static void eeepc_rfkill_exit(struct eeepc_laptop *eeepc)
rfkill_destroy(eeepc->wlan_rfkill); rfkill_destroy(eeepc->wlan_rfkill);
eeepc->wlan_rfkill = NULL; eeepc->wlan_rfkill = NULL;
} }
/*
* Refresh pci hotplug in case the rfkill state was changed after
* eeepc_unregister_rfkill_notifier()
*/
eeepc_rfkill_hotplug(eeepc);
if (eeepc->hotplug_slot) if (eeepc->hotplug_slot)
pci_hp_deregister(eeepc->hotplug_slot); pci_hp_deregister(eeepc->hotplug_slot);
...@@ -889,11 +916,6 @@ static int eeepc_rfkill_init(struct eeepc_laptop *eeepc) ...@@ -889,11 +916,6 @@ static int eeepc_rfkill_init(struct eeepc_laptop *eeepc)
eeepc_register_rfkill_notifier(eeepc, "\\_SB.PCI0.P0P5"); eeepc_register_rfkill_notifier(eeepc, "\\_SB.PCI0.P0P5");
eeepc_register_rfkill_notifier(eeepc, "\\_SB.PCI0.P0P6"); eeepc_register_rfkill_notifier(eeepc, "\\_SB.PCI0.P0P6");
eeepc_register_rfkill_notifier(eeepc, "\\_SB.PCI0.P0P7"); eeepc_register_rfkill_notifier(eeepc, "\\_SB.PCI0.P0P7");
/*
* Refresh pci hotplug in case the rfkill state was changed during
* setup.
*/
eeepc_rfkill_hotplug(eeepc);
exit: exit:
if (result && result != -ENODEV) if (result && result != -ENODEV)
...@@ -928,8 +950,11 @@ static int eeepc_hotk_restore(struct device *device) ...@@ -928,8 +950,11 @@ static int eeepc_hotk_restore(struct device *device)
struct eeepc_laptop *eeepc = dev_get_drvdata(device); struct eeepc_laptop *eeepc = dev_get_drvdata(device);
/* Refresh both wlan rfkill state and pci hotplug */ /* Refresh both wlan rfkill state and pci hotplug */
if (eeepc->wlan_rfkill) if (eeepc->wlan_rfkill) {
eeepc_rfkill_hotplug(eeepc); eeepc_rfkill_hotplug_update(eeepc, "\\_SB.PCI0.P0P5");
eeepc_rfkill_hotplug_update(eeepc, "\\_SB.PCI0.P0P6");
eeepc_rfkill_hotplug_update(eeepc, "\\_SB.PCI0.P0P7");
}
if (eeepc->bluetooth_rfkill) if (eeepc->bluetooth_rfkill)
rfkill_set_sw_state(eeepc->bluetooth_rfkill, rfkill_set_sw_state(eeepc->bluetooth_rfkill,
......
...@@ -934,6 +934,14 @@ static ssize_t sony_nc_sysfs_store(struct device *dev, ...@@ -934,6 +934,14 @@ static ssize_t sony_nc_sysfs_store(struct device *dev,
/* /*
* Backlight device * Backlight device
*/ */
struct sony_backlight_props {
struct backlight_device *dev;
int handle;
u8 offset;
u8 maxlvl;
};
struct sony_backlight_props sony_bl_props;
static int sony_backlight_update_status(struct backlight_device *bd) static int sony_backlight_update_status(struct backlight_device *bd)
{ {
return acpi_callsetfunc(sony_nc_acpi_handle, "SBRT", return acpi_callsetfunc(sony_nc_acpi_handle, "SBRT",
...@@ -954,21 +962,26 @@ static int sony_nc_get_brightness_ng(struct backlight_device *bd) ...@@ -954,21 +962,26 @@ static int sony_nc_get_brightness_ng(struct backlight_device *bd)
{ {
int result; int result;
int *handle = (int *)bl_get_data(bd); int *handle = (int *)bl_get_data(bd);
struct sony_backlight_props *sdev =
(struct sony_backlight_props *)bl_get_data(bd);
sony_call_snc_handle(*handle, 0x0200, &result); sony_call_snc_handle(sdev->handle, 0x0200, &result);
return result & 0xff; return (result & 0xff) - sdev->offset;
} }
static int sony_nc_update_status_ng(struct backlight_device *bd) static int sony_nc_update_status_ng(struct backlight_device *bd)
{ {
int value, result; int value, result;
int *handle = (int *)bl_get_data(bd); int *handle = (int *)bl_get_data(bd);
struct sony_backlight_props *sdev =
(struct sony_backlight_props *)bl_get_data(bd);
value = bd->props.brightness; value = bd->props.brightness + sdev->offset;
sony_call_snc_handle(*handle, 0x0100 | (value << 16), &result); if (sony_call_snc_handle(sdev->handle, 0x0100 | (value << 16), &result))
return -EIO;
return sony_nc_get_brightness_ng(bd); return value;
} }
static const struct backlight_ops sony_backlight_ops = { static const struct backlight_ops sony_backlight_ops = {
...@@ -981,8 +994,6 @@ static const struct backlight_ops sony_backlight_ng_ops = { ...@@ -981,8 +994,6 @@ static const struct backlight_ops sony_backlight_ng_ops = {
.update_status = sony_nc_update_status_ng, .update_status = sony_nc_update_status_ng,
.get_brightness = sony_nc_get_brightness_ng, .get_brightness = sony_nc_get_brightness_ng,
}; };
static int backlight_ng_handle;
static struct backlight_device *sony_backlight_device;
/* /*
* New SNC-only Vaios event mapping to driver known keys * New SNC-only Vaios event mapping to driver known keys
...@@ -1549,6 +1560,75 @@ static void sony_nc_kbd_backlight_resume(void) ...@@ -1549,6 +1560,75 @@ static void sony_nc_kbd_backlight_resume(void)
&ignore); &ignore);
} }
static void sony_nc_backlight_ng_read_limits(int handle,
struct sony_backlight_props *props)
{
int offset;
acpi_status status;
u8 brlvl, i;
u8 min = 0xff, max = 0x00;
struct acpi_object_list params;
union acpi_object in_obj;
union acpi_object *lvl_enum;
struct acpi_buffer buffer = { ACPI_ALLOCATE_BUFFER, NULL };
props->handle = handle;
props->offset = 0;
props->maxlvl = 0xff;
offset = sony_find_snc_handle(handle);
if (offset < 0)
return;
/* try to read the boundaries from ACPI tables, if we fail the above
* defaults should be reasonable
*/
params.count = 1;
params.pointer = &in_obj;
in_obj.type = ACPI_TYPE_INTEGER;
in_obj.integer.value = offset;
status = acpi_evaluate_object(sony_nc_acpi_handle, "SN06", &params,
&buffer);
if (ACPI_FAILURE(status))
return;
lvl_enum = (union acpi_object *) buffer.pointer;
if (!lvl_enum) {
pr_err("No SN06 return object.");
return;
}
if (lvl_enum->type != ACPI_TYPE_BUFFER) {
pr_err("Invalid SN06 return object 0x%.2x\n",
lvl_enum->type);
goto out_invalid;
}
/* the buffer lists brightness levels available, brightness levels are
* from 0 to 8 in the array, other values are used by ALS control.
*/
for (i = 0; i < 9 && i < lvl_enum->buffer.length; i++) {
brlvl = *(lvl_enum->buffer.pointer + i);
dprintk("Brightness level: %d\n", brlvl);
if (!brlvl)
break;
if (brlvl > max)
max = brlvl;
if (brlvl < min)
min = brlvl;
}
props->offset = min;
props->maxlvl = max;
dprintk("Brightness levels: min=%d max=%d\n", props->offset,
props->maxlvl);
out_invalid:
kfree(buffer.pointer);
return;
}
static void sony_nc_backlight_setup(void) static void sony_nc_backlight_setup(void)
{ {
acpi_handle unused; acpi_handle unused;
...@@ -1557,14 +1637,14 @@ static void sony_nc_backlight_setup(void) ...@@ -1557,14 +1637,14 @@ static void sony_nc_backlight_setup(void)
struct backlight_properties props; struct backlight_properties props;
if (sony_find_snc_handle(0x12f) != -1) { if (sony_find_snc_handle(0x12f) != -1) {
backlight_ng_handle = 0x12f;
ops = &sony_backlight_ng_ops; ops = &sony_backlight_ng_ops;
max_brightness = 0xff; sony_nc_backlight_ng_read_limits(0x12f, &sony_bl_props);
max_brightness = sony_bl_props.maxlvl - sony_bl_props.offset;
} else if (sony_find_snc_handle(0x137) != -1) { } else if (sony_find_snc_handle(0x137) != -1) {
backlight_ng_handle = 0x137;
ops = &sony_backlight_ng_ops; ops = &sony_backlight_ng_ops;
max_brightness = 0xff; sony_nc_backlight_ng_read_limits(0x137, &sony_bl_props);
max_brightness = sony_bl_props.maxlvl - sony_bl_props.offset;
} else if (ACPI_SUCCESS(acpi_get_handle(sony_nc_acpi_handle, "GBRT", } else if (ACPI_SUCCESS(acpi_get_handle(sony_nc_acpi_handle, "GBRT",
&unused))) { &unused))) {
...@@ -1577,22 +1657,22 @@ static void sony_nc_backlight_setup(void) ...@@ -1577,22 +1657,22 @@ static void sony_nc_backlight_setup(void)
memset(&props, 0, sizeof(struct backlight_properties)); memset(&props, 0, sizeof(struct backlight_properties));
props.type = BACKLIGHT_PLATFORM; props.type = BACKLIGHT_PLATFORM;
props.max_brightness = max_brightness; props.max_brightness = max_brightness;
sony_backlight_device = backlight_device_register("sony", NULL, sony_bl_props.dev = backlight_device_register("sony", NULL,
&backlight_ng_handle, &sony_bl_props,
ops, &props); ops, &props);
if (IS_ERR(sony_backlight_device)) { if (IS_ERR(sony_bl_props.dev)) {
pr_warning(DRV_PFX "unable to register backlight device\n"); pr_warn(DRV_PFX "unable to register backlight device\n");
sony_backlight_device = NULL; sony_bl_props.dev = NULL;
} else } else
sony_backlight_device->props.brightness = sony_bl_props.dev->props.brightness =
ops->get_brightness(sony_backlight_device); ops->get_brightness(sony_bl_props.dev);
} }
static void sony_nc_backlight_cleanup(void) static void sony_nc_backlight_cleanup(void)
{ {
if (sony_backlight_device) if (sony_bl_props.dev)
backlight_device_unregister(sony_backlight_device); backlight_device_unregister(sony_bl_props.dev);
} }
static int sony_nc_add(struct acpi_device *device) static int sony_nc_add(struct acpi_device *device)
...@@ -2590,7 +2670,7 @@ static long sonypi_misc_ioctl(struct file *fp, unsigned int cmd, ...@@ -2590,7 +2670,7 @@ static long sonypi_misc_ioctl(struct file *fp, unsigned int cmd,
mutex_lock(&spic_dev.lock); mutex_lock(&spic_dev.lock);
switch (cmd) { switch (cmd) {
case SONYPI_IOCGBRT: case SONYPI_IOCGBRT:
if (sony_backlight_device == NULL) { if (sony_bl_props.dev == NULL) {
ret = -EIO; ret = -EIO;
break; break;
} }
...@@ -2603,7 +2683,7 @@ static long sonypi_misc_ioctl(struct file *fp, unsigned int cmd, ...@@ -2603,7 +2683,7 @@ static long sonypi_misc_ioctl(struct file *fp, unsigned int cmd,
ret = -EFAULT; ret = -EFAULT;
break; break;
case SONYPI_IOCSBRT: case SONYPI_IOCSBRT:
if (sony_backlight_device == NULL) { if (sony_bl_props.dev == NULL) {
ret = -EIO; ret = -EIO;
break; break;
} }
...@@ -2617,8 +2697,8 @@ static long sonypi_misc_ioctl(struct file *fp, unsigned int cmd, ...@@ -2617,8 +2697,8 @@ static long sonypi_misc_ioctl(struct file *fp, unsigned int cmd,
break; break;
} }
/* sync the backlight device status */ /* sync the backlight device status */
sony_backlight_device->props.brightness = sony_bl_props.dev->props.brightness =
sony_backlight_get_brightness(sony_backlight_device); sony_backlight_get_brightness(sony_bl_props.dev);
break; break;
case SONYPI_IOCGBAT1CAP: case SONYPI_IOCGBAT1CAP:
if (ec_read16(SONYPI_BAT1_FULL, &val16)) { if (ec_read16(SONYPI_BAT1_FULL, &val16)) {
......
...@@ -128,7 +128,8 @@ enum { ...@@ -128,7 +128,8 @@ enum {
}; };
/* ACPI HIDs */ /* ACPI HIDs */
#define TPACPI_ACPI_HKEY_HID "IBM0068" #define TPACPI_ACPI_IBM_HKEY_HID "IBM0068"
#define TPACPI_ACPI_LENOVO_HKEY_HID "LEN0068"
#define TPACPI_ACPI_EC_HID "PNP0C09" #define TPACPI_ACPI_EC_HID "PNP0C09"
/* Input IDs */ /* Input IDs */
...@@ -3879,7 +3880,8 @@ static int hotkey_write(char *buf) ...@@ -3879,7 +3880,8 @@ static int hotkey_write(char *buf)
} }
static const struct acpi_device_id ibm_htk_device_ids[] = { static const struct acpi_device_id ibm_htk_device_ids[] = {
{TPACPI_ACPI_HKEY_HID, 0}, {TPACPI_ACPI_IBM_HKEY_HID, 0},
{TPACPI_ACPI_LENOVO_HKEY_HID, 0},
{"", 0}, {"", 0},
}; };
......
Markdown is supported
0% .
You are about to add 0 people to the discussion. Proceed with caution.
先完成此消息的编辑!
想要评论请 注册