diff options
author | Linus Torvalds <torvalds@linux-foundation.org> | 2014-10-09 16:07:43 -0400 |
---|---|---|
committer | Linus Torvalds <torvalds@linux-foundation.org> | 2014-10-09 16:07:43 -0400 |
commit | b528392669415dc1e53a047215e5ad6c2de879fc (patch) | |
tree | d19aa6e1464ef7c7d9f399ac8ec9a7707e5ba6b4 /drivers/acpi | |
parent | 80213c03c4151d900cf293ef0fc51f8d88495e14 (diff) | |
parent | 9f1a053296953c69d7f23511db9441290cb89e2c (diff) |
Merge tag 'pm+acpi-3.18-rc1' of git://git.kernel.org/pub/scm/linux/kernel/git/rafael/linux-pm
Pull ACPI and power management updates from Rafael Wysocki:
"Features-wise, to me the most important this time is a rework of
wakeup interrupts handling in the core that makes them work
consistently across all of the available sleep states, including
suspend-to-idle. Many thanks to Thomas Gleixner for his help with
this work.
Second is an update of the generic PM domains code that has been in
need of some care for quite a while. Unused code is being removed, DT
support is being added and domains are now going to be attached to
devices in bus type code in analogy with the ACPI PM domain. The
majority of work here was done by Ulf Hansson who also has been the
most active developer this time.
Apart from this we have a traditional ACPICA update, this time to
upstream version 20140828 and a few ACPI wakeup interrupts handling
patches on top of the general rework mentioned above. There also are
several cpufreq commits including renaming the cpufreq-cpu0 driver to
cpufreq-dt, as this is what implements generic DT-based cpufreq
support, and a new DT-based idle states infrastructure for cpuidle.
In addition to that, the ACPI LPSS driver is updated, ACPI support for
Apple machines is improved, a few bugs are fixed and a few cleanups
are made all over.
Finally, the Adaptive Voltage Scaling (AVS) subsystem now has a tree
maintained by Kevin Hilman that will be merged through the PM tree.
Numbers-wise, the generic PM domains update takes the lead this time
with 32 non-merge commits, second is cpufreq (15 commits) and the 3rd
place goes to the wakeup interrupts handling rework (13 commits).
Specifics:
- Rework the handling of wakeup IRQs by the IRQ core such that all of
them will be switched over to "wakeup" mode in suspend_device_irqs()
and in that mode the first interrupt will abort system suspend in
progress or wake up the system if already in suspend-to-idle (or
equivalent) without executing any interrupt handlers. Among other
things that eliminates the wakeup-related motivation to use the
IRQF_NO_SUSPEND interrupt flag with interrupts which don't really
need it and should not use it (Thomas Gleixner and Rafael Wysocki)
- Switch over ACPI to handling wakeup interrupts with the help of the
new mechanism introduced by the above IRQ core rework (Rafael Wysocki)
- Rework the core generic PM domains code to eliminate code that's
not used, add DT support and add a generic mechanism by which
devices can be added to PM domains automatically during enumeration
(Ulf Hansson, Geert Uytterhoeven and Tomasz Figa).
- Add debugfs-based mechanics for debugging generic PM domains
(Maciej Matraszek).
- ACPICA update to upstream version 20140828. Included are updates
related to the SRAT and GTDT tables and the _PSx methods are in the
METHOD_NAME list now (Bob Moore and Hanjun Guo).
- Add _OSI("Darwin") support to the ACPI core (unfortunately, that
can't really be done in a straightforward way) to prevent
Thunderbolt from being turned off on Apple systems after boot (or
after resume from system suspend) and rework the ACPI Smart Battery
Subsystem (SBS) driver to work correctly with Apple platforms
(Matthew Garrett and Andreas Noever).
- ACPI LPSS (Low-Power Subsystem) driver update cleaning up the code,
adding support for 133MHz I2C source clock on Intel Baytrail to it
and making it avoid using UART RTS override with Auto Flow Control
(Heikki Krogerus).
- ACPI backlight updates removing the video_set_use_native_backlight
quirk which is not necessary any more, making the code check the
list of output devices returned by the _DOD method to avoid
creating acpi_video interfaces that won't work and adding a quirk
for Lenovo Ideapad Z570 (Hans de Goede, Aaron Lu and Stepan Bujnak)
- New Win8 ACPI OSI quirks for some Dell laptops (Edward Lin)
- Assorted ACPI code cleanups (Fabian Frederick, Rasmus Villemoes,
Sudip Mukherjee, Yijing Wang, and Zhang Rui)
- cpufreq core updates and cleanups (Viresh Kumar, Preeti U Murthy,
Rasmus Villemoes)
- cpufreq driver updates: cpufreq-cpu0/cpufreq-dt (driver name change
among other things), ppc-corenet, powernv (Viresh Kumar, Preeti U
Murthy, Shilpasri G Bhat, Lucas Stach)
- cpuidle support for DT-based idle states infrastructure, new ARM64
cpuidle driver, cpuidle core cleanups (Lorenzo Pieralisi, Rasmus
Villemoes)
- ARM big.LITTLE cpuidle driver updates: support for DT-based
initialization and Exynos5800 compatible string (Lorenzo Pieralisi,
Kevin Hilman)
- Rework of the test_suspend kernel command line argument and a new
trace event for console resume (Srinivas Pandruvada, Todd E Brandt)
- Second attempt to optimize swsusp_free() (hibernation core) to make
it avoid going through all PFNs which may be way too slow on some
systems (Joerg Roedel)
- devfreq updates (Paul Bolle, Punit Agrawal, Ãrjan Eide).
- rockchip-io Adaptive Voltage Scaling (AVS) driver and AVS entry
update in MAINTAINERS (Heiko Stübner, Kevin Hilman)
- PM core fix related to clock management (Geert Uytterhoeven)
- PM core's sysfs code cleanup (Johannes Berg)"
* tag 'pm+acpi-3.18-rc1' of git://git.kernel.org/pub/scm/linux/kernel/git/rafael/linux-pm: (105 commits)
ACPI / fan: printk replacement
PM / clk: Fix crash in clocks management code if !CONFIG_PM_RUNTIME
PM / Domains: Rename cpu_data to cpuidle_data
cpufreq: cpufreq-dt: fix potential double put of cpu OF node
cpufreq: cpu0: rename driver and internals to 'cpufreq_dt'
PM / hibernate: Iterate over set bits instead of PFNs in swsusp_free()
cpufreq: ppc-corenet: remove duplicate update of cpu_data
ACPI / sleep: Rework the handling of ACPI GPE wakeup from suspend-to-idle
PM / sleep: Rename platform suspend/resume functions in suspend.c
PM / sleep: Export dpm_suspend_late/noirq() and dpm_resume_early/noirq()
ACPICA: Introduce acpi_enable_all_wakeup_gpes()
ACPICA: Clear all non-wakeup GPEs in acpi_hw_enable_wakeup_gpe_block()
ACPI / video: check _DOD list when creating backlight devices
PM / Domains: Move dev_pm_domain_attach|detach() to pm_domain.h
cpufreq: Replace strnicmp with strncasecmp
cpufreq: powernv: Set the cpus to nominal frequency during reboot/kexec
cpufreq: powernv: Set the pstate of the last hotplugged out cpu in policy->cpus to minimum
cpufreq: Allow stop CPU callback to be used by all cpufreq drivers
PM / devfreq: exynos: Enable building exynos PPMU as module
PM / devfreq: Export helper functions for drivers
...
Diffstat (limited to 'drivers/acpi')
-rw-r--r-- | drivers/acpi/acpi_lpss.c | 167 | ||||
-rw-r--r-- | drivers/acpi/acpi_pnp.c | 4 | ||||
-rw-r--r-- | drivers/acpi/acpica/evxfgpe.c | 32 | ||||
-rw-r--r-- | drivers/acpi/acpica/hwgpe.c | 8 | ||||
-rw-r--r-- | drivers/acpi/acpica/utresrc.c | 4 | ||||
-rw-r--r-- | drivers/acpi/battery.c | 2 | ||||
-rw-r--r-- | drivers/acpi/blacklist.c | 36 | ||||
-rw-r--r-- | drivers/acpi/device_pm.c | 71 | ||||
-rw-r--r-- | drivers/acpi/fan.c | 18 | ||||
-rw-r--r-- | drivers/acpi/osl.c | 12 | ||||
-rw-r--r-- | drivers/acpi/pci_root.c | 14 | ||||
-rw-r--r-- | drivers/acpi/processor_core.c | 6 | ||||
-rw-r--r-- | drivers/acpi/sbs.c | 80 | ||||
-rw-r--r-- | drivers/acpi/sleep.c | 16 | ||||
-rw-r--r-- | drivers/acpi/utils.c | 1 | ||||
-rw-r--r-- | drivers/acpi/video.c | 291 | ||||
-rw-r--r-- | drivers/acpi/video_detect.c | 8 |
17 files changed, 319 insertions, 451 deletions
diff --git a/drivers/acpi/acpi_lpss.c b/drivers/acpi/acpi_lpss.c index b0ea767c8696..93d160661f4c 100644 --- a/drivers/acpi/acpi_lpss.c +++ b/drivers/acpi/acpi_lpss.c @@ -54,55 +54,58 @@ ACPI_MODULE_NAME("acpi_lpss"); #define LPSS_PRV_REG_COUNT 9 -struct lpss_shared_clock { - const char *name; - unsigned long rate; - struct clk *clk; -}; +/* LPSS Flags */ +#define LPSS_CLK BIT(0) +#define LPSS_CLK_GATE BIT(1) +#define LPSS_CLK_DIVIDER BIT(2) +#define LPSS_LTR BIT(3) +#define LPSS_SAVE_CTX BIT(4) struct lpss_private_data; struct lpss_device_desc { - bool clk_required; - const char *clkdev_name; - bool ltr_required; + unsigned int flags; unsigned int prv_offset; size_t prv_size_override; - bool clk_divider; - bool clk_gate; - bool save_ctx; - struct lpss_shared_clock *shared_clock; void (*setup)(struct lpss_private_data *pdata); }; static struct lpss_device_desc lpss_dma_desc = { - .clk_required = true, - .clkdev_name = "hclk", + .flags = LPSS_CLK, }; struct lpss_private_data { void __iomem *mmio_base; resource_size_t mmio_size; + unsigned int fixed_clk_rate; struct clk *clk; const struct lpss_device_desc *dev_desc; u32 prv_reg_ctx[LPSS_PRV_REG_COUNT]; }; +/* UART Component Parameter Register */ +#define LPSS_UART_CPR 0xF4 +#define LPSS_UART_CPR_AFCE BIT(4) + static void lpss_uart_setup(struct lpss_private_data *pdata) { unsigned int offset; - u32 reg; + u32 val; offset = pdata->dev_desc->prv_offset + LPSS_TX_INT; - reg = readl(pdata->mmio_base + offset); - writel(reg | LPSS_TX_INT_MASK, pdata->mmio_base + offset); - - offset = pdata->dev_desc->prv_offset + LPSS_GENERAL; - reg = readl(pdata->mmio_base + offset); - writel(reg | LPSS_GENERAL_UART_RTS_OVRD, pdata->mmio_base + offset); + val = readl(pdata->mmio_base + offset); + writel(val | LPSS_TX_INT_MASK, pdata->mmio_base + offset); + + val = readl(pdata->mmio_base + LPSS_UART_CPR); + if (!(val & LPSS_UART_CPR_AFCE)) { + offset = pdata->dev_desc->prv_offset + LPSS_GENERAL; + val = readl(pdata->mmio_base + offset); + val |= LPSS_GENERAL_UART_RTS_OVRD; + writel(val, pdata->mmio_base + offset); + } } -static void lpss_i2c_setup(struct lpss_private_data *pdata) +static void byt_i2c_setup(struct lpss_private_data *pdata) { unsigned int offset; u32 val; @@ -111,100 +114,56 @@ static void lpss_i2c_setup(struct lpss_private_data *pdata) val = readl(pdata->mmio_base + offset); val |= LPSS_RESETS_RESET_APB | LPSS_RESETS_RESET_FUNC; writel(val, pdata->mmio_base + offset); -} -static struct lpss_device_desc wpt_dev_desc = { - .clk_required = true, - .prv_offset = 0x800, - .ltr_required = true, - .clk_divider = true, - .clk_gate = true, -}; + if (readl(pdata->mmio_base + pdata->dev_desc->prv_offset)) + pdata->fixed_clk_rate = 133000000; +} static struct lpss_device_desc lpt_dev_desc = { - .clk_required = true, + .flags = LPSS_CLK | LPSS_CLK_GATE | LPSS_CLK_DIVIDER | LPSS_LTR, .prv_offset = 0x800, - .ltr_required = true, - .clk_divider = true, - .clk_gate = true, }; static struct lpss_device_desc lpt_i2c_dev_desc = { - .clk_required = true, + .flags = LPSS_CLK | LPSS_CLK_GATE | LPSS_LTR, .prv_offset = 0x800, - .ltr_required = true, - .clk_gate = true, }; static struct lpss_device_desc lpt_uart_dev_desc = { - .clk_required = true, + .flags = LPSS_CLK | LPSS_CLK_GATE | LPSS_CLK_DIVIDER | LPSS_LTR, .prv_offset = 0x800, - .ltr_required = true, - .clk_divider = true, - .clk_gate = true, .setup = lpss_uart_setup, }; static struct lpss_device_desc lpt_sdio_dev_desc = { + .flags = LPSS_LTR, .prv_offset = 0x1000, .prv_size_override = 0x1018, - .ltr_required = true, -}; - -static struct lpss_shared_clock pwm_clock = { - .name = "pwm_clk", - .rate = 25000000, }; static struct lpss_device_desc byt_pwm_dev_desc = { - .clk_required = true, - .save_ctx = true, - .shared_clock = &pwm_clock, + .flags = LPSS_SAVE_CTX, }; static struct lpss_device_desc byt_uart_dev_desc = { - .clk_required = true, + .flags = LPSS_CLK | LPSS_CLK_GATE | LPSS_CLK_DIVIDER | LPSS_SAVE_CTX, .prv_offset = 0x800, - .clk_divider = true, - .clk_gate = true, - .save_ctx = true, .setup = lpss_uart_setup, }; static struct lpss_device_desc byt_spi_dev_desc = { - .clk_required = true, + .flags = LPSS_CLK | LPSS_CLK_GATE | LPSS_CLK_DIVIDER | LPSS_SAVE_CTX, .prv_offset = 0x400, - .clk_divider = true, - .clk_gate = true, - .save_ctx = true, }; static struct lpss_device_desc byt_sdio_dev_desc = { - .clk_required = true, -}; - -static struct lpss_shared_clock i2c_clock = { - .name = "i2c_clk", - .rate = 100000000, + .flags = LPSS_CLK, }; static struct lpss_device_desc byt_i2c_dev_desc = { - .clk_required = true, + .flags = LPSS_CLK | LPSS_SAVE_CTX, .prv_offset = 0x800, - .save_ctx = true, - .shared_clock = &i2c_clock, - .setup = lpss_i2c_setup, -}; - -static struct lpss_shared_clock bsw_pwm_clock = { - .name = "pwm_clk", - .rate = 19200000, -}; - -static struct lpss_device_desc bsw_pwm_dev_desc = { - .clk_required = true, - .save_ctx = true, - .shared_clock = &bsw_pwm_clock, + .setup = byt_i2c_setup, }; #else @@ -237,7 +196,7 @@ static const struct acpi_device_id acpi_lpss_device_ids[] = { { "INT33FC", }, /* Braswell LPSS devices */ - { "80862288", LPSS_ADDR(bsw_pwm_dev_desc) }, + { "80862288", LPSS_ADDR(byt_pwm_dev_desc) }, { "8086228A", LPSS_ADDR(byt_uart_dev_desc) }, { "8086228E", LPSS_ADDR(byt_spi_dev_desc) }, { "808622C1", LPSS_ADDR(byt_i2c_dev_desc) }, @@ -251,7 +210,8 @@ static const struct acpi_device_id acpi_lpss_device_ids[] = { { "INT3436", LPSS_ADDR(lpt_sdio_dev_desc) }, { "INT3437", }, - { "INT3438", LPSS_ADDR(wpt_dev_desc) }, + /* Wildcat Point LPSS devices */ + { "INT3438", LPSS_ADDR(lpt_dev_desc) }, { } }; @@ -276,7 +236,6 @@ static int register_device_clock(struct acpi_device *adev, struct lpss_private_data *pdata) { const struct lpss_device_desc *dev_desc = pdata->dev_desc; - struct lpss_shared_clock *shared_clock = dev_desc->shared_clock; const char *devname = dev_name(&adev->dev); struct clk *clk = ERR_PTR(-ENODEV); struct lpss_clk_data *clk_data; @@ -289,12 +248,7 @@ static int register_device_clock(struct acpi_device *adev, clk_data = platform_get_drvdata(lpss_clk_dev); if (!clk_data) return -ENODEV; - - if (dev_desc->clkdev_name) { - clk_register_clkdev(clk_data->clk, dev_desc->clkdev_name, - devname); - return 0; - } + clk = clk_data->clk; if (!pdata->mmio_base || pdata->mmio_size < dev_desc->prv_offset + LPSS_CLK_SIZE) @@ -303,24 +257,19 @@ static int register_device_clock(struct acpi_device *adev, parent = clk_data->name; prv_base = pdata->mmio_base + dev_desc->prv_offset; - if (shared_clock) { - clk = shared_clock->clk; - if (!clk) { - clk = clk_register_fixed_rate(NULL, shared_clock->name, - "lpss_clk", 0, - shared_clock->rate); - shared_clock->clk = clk; - } - parent = shared_clock->name; + if (pdata->fixed_clk_rate) { + clk = clk_register_fixed_rate(NULL, devname, parent, 0, + pdata->fixed_clk_rate); + goto out; } - if (dev_desc->clk_gate) { + if (dev_desc->flags & LPSS_CLK_GATE) { clk = clk_register_gate(NULL, devname, parent, 0, prv_base, 0, 0, NULL); parent = devname; } - if (dev_desc->clk_divider) { + if (dev_desc->flags & LPSS_CLK_DIVIDER) { /* Prevent division by zero */ if (!readl(prv_base)) writel(LPSS_CLK_DIVIDER_DEF_MASK, prv_base); @@ -344,7 +293,7 @@ static int register_device_clock(struct acpi_device *adev, kfree(parent); kfree(clk_name); } - +out: if (IS_ERR(clk)) return PTR_ERR(clk); @@ -392,7 +341,10 @@ static int acpi_lpss_create_device(struct acpi_device *adev, pdata->dev_desc = dev_desc; - if (dev_desc->clk_required) { + if (dev_desc->setup) + dev_desc->setup(pdata); + + if (dev_desc->flags & LPSS_CLK) { ret = register_device_clock(adev, pdata); if (ret) { /* Skip the device, but continue the namespace scan. */ @@ -413,9 +365,6 @@ static int acpi_lpss_create_device(struct acpi_device *adev, goto err_out; } - if (dev_desc->setup) - dev_desc->setup(pdata); - adev->driver_data = pdata; pdev = acpi_create_platform_device(adev); if (!IS_ERR_OR_NULL(pdev)) { @@ -692,19 +641,19 @@ static int acpi_lpss_platform_notify(struct notifier_block *nb, switch (action) { case BUS_NOTIFY_BOUND_DRIVER: - if (pdata->dev_desc->save_ctx) + if (pdata->dev_desc->flags & LPSS_SAVE_CTX) pdev->dev.pm_domain = &acpi_lpss_pm_domain; break; case BUS_NOTIFY_UNBOUND_DRIVER: - if (pdata->dev_desc->save_ctx) + if (pdata->dev_desc->flags & LPSS_SAVE_CTX) pdev->dev.pm_domain = NULL; break; case BUS_NOTIFY_ADD_DEVICE: - if (pdata->dev_desc->ltr_required) + if (pdata->dev_desc->flags & LPSS_LTR) return sysfs_create_group(&pdev->dev.kobj, &lpss_attr_group); case BUS_NOTIFY_DEL_DEVICE: - if (pdata->dev_desc->ltr_required) + if (pdata->dev_desc->flags & LPSS_LTR) sysfs_remove_group(&pdev->dev.kobj, &lpss_attr_group); default: break; @@ -721,7 +670,7 @@ static void acpi_lpss_bind(struct device *dev) { struct lpss_private_data *pdata = acpi_driver_data(ACPI_COMPANION(dev)); - if (!pdata || !pdata->mmio_base || !pdata->dev_desc->ltr_required) + if (!pdata || !pdata->mmio_base || !(pdata->dev_desc->flags & LPSS_LTR)) return; if (pdata->mmio_size >= pdata->dev_desc->prv_offset + LPSS_LTR_SIZE) diff --git a/drivers/acpi/acpi_pnp.c b/drivers/acpi/acpi_pnp.c index 1f8b20496f32..b193f8425999 100644 --- a/drivers/acpi/acpi_pnp.c +++ b/drivers/acpi/acpi_pnp.c @@ -130,10 +130,6 @@ static const struct acpi_device_id acpi_pnp_device_ids[] = { {"PNP0401"}, /* ECP Printer Port */ /* apple-gmux */ {"APP000B"}, - /* fujitsu-laptop.c */ - {"FUJ02bf"}, - {"FUJ02B1"}, - {"FUJ02E3"}, /* system */ {"PNP0c02"}, /* General ID for reserving resources */ {"PNP0c01"}, /* memory controller */ diff --git a/drivers/acpi/acpica/evxfgpe.c b/drivers/acpi/acpica/evxfgpe.c index 0cf159cc6e6d..56710a03c9b0 100644 --- a/drivers/acpi/acpica/evxfgpe.c +++ b/drivers/acpi/acpica/evxfgpe.c @@ -596,6 +596,38 @@ acpi_status acpi_enable_all_runtime_gpes(void) ACPI_EXPORT_SYMBOL(acpi_enable_all_runtime_gpes) +/****************************************************************************** + * + * FUNCTION: acpi_enable_all_wakeup_gpes + * + * PARAMETERS: None + * + * RETURN: Status + * + * DESCRIPTION: Enable all "wakeup" GPEs and disable all of the other GPEs, in + * all GPE blocks. + * + ******************************************************************************/ + +acpi_status acpi_enable_all_wakeup_gpes(void) +{ + acpi_status status; + + ACPI_FUNCTION_TRACE(acpi_enable_all_wakeup_gpes); + + status = acpi_ut_acquire_mutex(ACPI_MTX_EVENTS); + if (ACPI_FAILURE(status)) { + return_ACPI_STATUS(status); + } + + status = acpi_hw_enable_all_wakeup_gpes(); + (void)acpi_ut_release_mutex(ACPI_MTX_EVENTS); + + return_ACPI_STATUS(status); +} + +ACPI_EXPORT_SYMBOL(acpi_enable_all_wakeup_gpes) + /******************************************************************************* * * FUNCTION: acpi_install_gpe_block diff --git a/drivers/acpi/acpica/hwgpe.c b/drivers/acpi/acpica/hwgpe.c index 2e6caabba07a..ea62d40fd161 100644 --- a/drivers/acpi/acpica/hwgpe.c +++ b/drivers/acpi/acpica/hwgpe.c @@ -396,11 +396,11 @@ acpi_hw_enable_wakeup_gpe_block(struct acpi_gpe_xrupt_info *gpe_xrupt_info, /* Examine each GPE Register within the block */ for (i = 0; i < gpe_block->register_count; i++) { - if (!gpe_block->register_info[i].enable_for_wake) { - continue; - } - /* Enable all "wake" GPEs in this register */ + /* + * Enable all "wake" GPEs in this register and disable the + * remaining ones. + */ status = acpi_hw_write(gpe_block->register_info[i].enable_for_wake, diff --git a/drivers/acpi/acpica/utresrc.c b/drivers/acpi/acpica/utresrc.c index 14cb6c0c8be2..5cd017c7ac0e 100644 --- a/drivers/acpi/acpica/utresrc.c +++ b/drivers/acpi/acpica/utresrc.c @@ -87,7 +87,9 @@ const char *acpi_gbl_io_decode[] = { const char *acpi_gbl_ll_decode[] = { "ActiveHigh", - "ActiveLow" + "ActiveLow", + "ActiveBoth", + "Reserved" }; const char *acpi_gbl_max_decode[] = { diff --git a/drivers/acpi/battery.c b/drivers/acpi/battery.c index 5fdfe65fe165..8ec8a89a20ab 100644 --- a/drivers/acpi/battery.c +++ b/drivers/acpi/battery.c @@ -695,7 +695,7 @@ static void acpi_battery_quirks(struct acpi_battery *battery) if (battery->power_unit && dmi_name_in_vendors("LENOVO")) { const char *s; s = dmi_get_system_info(DMI_PRODUCT_VERSION); - if (s && !strnicmp(s, "ThinkPad", 8)) { + if (s && !strncasecmp(s, "ThinkPad", 8)) { dmi_walk(find_battery, battery); if (test_bit(ACPI_BATTERY_QUIRK_THINKPAD_MAH, &battery->flags) && diff --git a/drivers/acpi/blacklist.c b/drivers/acpi/blacklist.c index 36eb42e3b0bb..ed122e17636e 100644 --- a/drivers/acpi/blacklist.c +++ b/drivers/acpi/blacklist.c @@ -247,8 +247,8 @@ static struct dmi_system_id acpi_osi_dmi_table[] __initdata = { }, /* - * These machines will power on immediately after shutdown when - * reporting the Windows 2012 OSI. + * The wireless hotkey does not work on those machines when + * returning true for _OSI("Windows 2012") */ { .callback = dmi_disable_osi_win8, @@ -258,6 +258,38 @@ static struct dmi_system_id acpi_osi_dmi_table[] __initdata = { DMI_MATCH(DMI_PRODUCT_NAME, "Inspiron 7737"), }, }, + { + .callback = dmi_disable_osi_win8, + .ident = "Dell Inspiron 7537", + .matches = { + DMI_MATCH(DMI_SYS_VENDOR, "Dell Inc."), + DMI_MATCH(DMI_PRODUCT_NAME, "Inspiron 7537"), + }, + }, + { + .callback = dmi_disable_osi_win8, + .ident = "Dell Inspiron 5437", + .matches = { + DMI_MATCH(DMI_SYS_VENDOR, "Dell Inc."), + DMI_MATCH(DMI_PRODUCT_NAME, "Inspiron 5437"), + }, + }, + { + .callback = dmi_disable_osi_win8, + .ident = "Dell Inspiron 3437", + .matches = { + DMI_MATCH(DMI_SYS_VENDOR, "Dell Inc."), + DMI_MATCH(DMI_PRODUCT_NAME, "Inspiron 3437"), + }, + }, + { + .callback = dmi_disable_osi_win8, + .ident = "Dell Vostro 3446", + .matches = { + DMI_MATCH(DMI_SYS_VENDOR, "Dell Inc."), + DMI_MATCH(DMI_PRODUCT_NAME, "Vostro 3446"), + }, + }, /* * BIOS invocation of _OSI(Linux) is almost always a BIOS bug. diff --git a/drivers/acpi/device_pm.c b/drivers/acpi/device_pm.c index 67075f800e34..bea6896be122 100644 --- a/drivers/acpi/device_pm.c +++ b/drivers/acpi/device_pm.c @@ -1041,6 +1041,40 @@ static struct dev_pm_domain acpi_general_pm_domain = { }; /** + * acpi_dev_pm_detach - Remove ACPI power management from the device. + * @dev: Device to take care of. + * @power_off: Whether or not to try to remove power from the device. + * + * Remove the device from the general ACPI PM domain and remove its wakeup + * notifier. If @power_off is set, additionally remove power from the device if + * possible. + * + * Callers must ensure proper synchronization of this function with power + * management callbacks. + */ +static void acpi_dev_pm_detach(struct device *dev, bool power_off) +{ + struct acpi_device *adev = ACPI_COMPANION(dev); + + if (adev && dev->pm_domain == &acpi_general_pm_domain) { + dev->pm_domain = NULL; + acpi_remove_pm_notifier(adev); + if (power_off) { + /* + * If the device's PM QoS resume latency limit or flags + * have been exposed to user space, they have to be + * hidden at this point, so that they don't affect the + * choice of the low-power state to put the device into. + */ + dev_pm_qos_hide_latency_limit(dev); + dev_pm_qos_hide_flags(dev); + acpi_device_wakeup(adev, ACPI_STATE_S0, false); + acpi_dev_pm_low_power(dev, adev, ACPI_STATE_S0); + } + } +} + +/** * acpi_dev_pm_attach - Prepare device for ACPI power management. * @dev: Device to prepare. * @power_on: Whether or not to power on the device. @@ -1072,42 +1106,9 @@ int acpi_dev_pm_attach(struct device *dev, bool power_on) acpi_dev_pm_full_power(adev); acpi_device_wakeup(adev, ACPI_STATE_S0, false); } + + dev->pm_domain->detach = acpi_dev_pm_detach; return 0; } EXPORT_SYMBOL_GPL(acpi_dev_pm_attach); - -/** - * acpi_dev_pm_detach - Remove ACPI power management from the device. - * @dev: Device to take care of. - * @power_off: Whether or not to try to remove power from the device. - * - * Remove the device from the general ACPI PM domain and remove its wakeup - * notifier. If @power_off is set, additionally remove power from the device if - * possible. - * - * Callers must ensure proper synchronization of this function with power - * management callbacks. - */ -void acpi_dev_pm_detach(struct device *dev, bool power_off) -{ - struct acpi_device *adev = ACPI_COMPANION(dev); - - if (adev && dev->pm_domain == &acpi_general_pm_domain) { - dev->pm_domain = NULL; - acpi_remove_pm_notifier(adev); - if (power_off) { - /* - * If the device's PM QoS resume latency limit or flags - * have been exposed to user space, they have to be - * hidden at this point, so that they don't affect the - * choice of the low-power state to put the device into. - */ - dev_pm_qos_hide_latency_limit(dev); - dev_pm_qos_hide_flags(dev); - acpi_device_wakeup(adev, ACPI_STATE_S0, false); - acpi_dev_pm_low_power(dev, adev, ACPI_STATE_S0); - } - } -} -EXPORT_SYMBOL_GPL(acpi_dev_pm_detach); #endif /* CONFIG_PM */ diff --git a/drivers/acpi/fan.c b/drivers/acpi/fan.c index 8acf53e62966..5328b1090e08 100644 --- a/drivers/acpi/fan.c +++ b/drivers/acpi/fan.c @@ -27,12 +27,10 @@ #include <linux/module.h> #include <linux/init.h> #include <linux/types.h> -#include <asm/uaccess.h> +#include <linux/uaccess.h> #include <linux/thermal.h> #include <linux/acpi.h> -#define PREFIX "ACPI: " - #define ACPI_FAN_CLASS "fan" #define ACPI_FAN_FILE_STATE "state" @@ -127,8 +125,9 @@ static const struct thermal_cooling_device_ops fan_cooling_ops = { }; /* -------------------------------------------------------------------------- - Driver Interface - -------------------------------------------------------------------------- */ + * Driver Interface + * -------------------------------------------------------------------------- +*/ static int acpi_fan_add(struct acpi_device *device) { @@ -143,7 +142,7 @@ static int acpi_fan_add(struct acpi_device *device) result = acpi_bus_update_power(device->handle, NULL); if (result) { - printk(KERN_ERR PREFIX "Setting initial power state\n"); + dev_err(&device->dev, "Setting initial power state\n"); goto end; } @@ -168,10 +167,9 @@ static int acpi_fan_add(struct acpi_device *device) &device->dev.kobj, "device"); if (result) - dev_err(&device->dev, "Failed to create sysfs link " - "'device'\n"); + dev_err(&device->dev, "Failed to create sysfs link 'device'\n"); - printk(KERN_INFO PREFIX "%s [%s] (%s)\n", + dev_info(&device->dev, "ACPI: %s [%s] (%s)\n", acpi_device_name(device), acpi_device_bid(device), !device->power.state ? "on" : "off"); @@ -217,7 +215,7 @@ static int acpi_fan_resume(struct device *dev) result = acpi_bus_update_power(to_acpi_device(dev)->handle, NULL); if (result) - printk(KERN_ERR PREFIX "Error updating fan power state\n"); + dev_err(dev, "Error updating fan power state\n"); return result; } diff --git a/drivers/acpi/osl.c b/drivers/acpi/osl.c index 3abe9b223ba7..9964f70be98d 100644 --- a/drivers/acpi/osl.c +++ b/drivers/acpi/osl.c @@ -152,6 +152,16 @@ static u32 acpi_osi_handler(acpi_string interface, u32 supported) osi_linux.dmi ? " via DMI" : ""); } + if (!strcmp("Darwin", interface)) { + /* + * Apple firmware will behave poorly if it receives positive + * answers to "Darwin" and any other OS. Respond positively + * to Darwin and then disable all other vendor strings. + */ + acpi_update_interfaces(ACPI_DISABLE_ALL_VENDOR_STRINGS); + supported = ACPI_UINT32_MAX; + } + return supported; } @@ -825,7 +835,7 @@ acpi_os_install_interrupt_handler(u32 gsi, acpi_osd_handler handler, acpi_irq_handler = handler; acpi_irq_context = context; - if (request_irq(irq, acpi_irq, IRQF_SHARED | IRQF_NO_SUSPEND, "acpi", acpi_irq)) { + if (request_irq(irq, acpi_irq, IRQF_SHARED, "acpi", acpi_irq)) { printk(KERN_ERR PREFIX "SCI (IRQ%d) allocation failed\n", irq); acpi_irq_handler = NULL; return AE_NOT_ACQUIRED; diff --git a/drivers/acpi/pci_root.c b/drivers/acpi/pci_root.c index e6ae603ed1a1..cd4de7e038ea 100644 --- a/drivers/acpi/pci_root.c +++ b/drivers/acpi/pci_root.c @@ -35,6 +35,7 @@ #include <linux/pci-aspm.h> #include <linux/acpi.h> #include <linux/slab.h> +#include <linux/dmi.h> #include <acpi/apei.h> /* for acpi_hest_init() */ #include "internal.h" @@ -430,6 +431,19 @@ static void negotiate_os_control(struct acpi_pci_root *root, int *no_aspm, acpi_handle handle = device->handle; /* + * Apple always return failure on _OSC calls when _OSI("Darwin") has + * been called successfully. We know the feature set supported by the + * platform, so avoid calling _OSC at all + */ + + if (dmi_match(DMI_SYS_VENDOR, "Apple Inc.")) { + root->osc_control_set = ~OSC_PCI_EXPRESS_PME_CONTROL; + decode_osc_control(root, "OS assumes control of", + root->osc_control_set); + return; + } + + /* * All supported architectures that use ACPI have support for * PCI domains, so we indicate this in _OSC support capabilities. */ diff --git a/drivers/acpi/processor_core.c b/drivers/acpi/processor_core.c index e32321ce9a5c..ef58f46c8442 100644 --- a/drivers/acpi/processor_core.c +++ b/drivers/acpi/processor_core.c @@ -16,7 +16,7 @@ static int map_lapic_id(struct acpi_subtable_header *entry, u32 acpi_id, int *apic_id) { struct acpi_madt_local_apic *lapic = - (struct acpi_madt_local_apic *)entry; + container_of(entry, struct acpi_madt_local_apic, header); if (!(lapic->lapic_flags & ACPI_MADT_ENABLED)) return -ENODEV; @@ -32,7 +32,7 @@ static int map_x2apic_id(struct acpi_subtable_header *entry, int device_declaration, u32 acpi_id, int *apic_id) { struct acpi_madt_local_x2apic *apic = - (struct acpi_madt_local_x2apic *)entry; + container_of(entry, struct acpi_madt_local_x2apic, header); if (!(apic->lapic_flags & ACPI_MADT_ENABLED)) return -ENODEV; @@ -49,7 +49,7 @@ static int map_lsapic_id(struct acpi_subtable_header *entry, int device_declaration, u32 acpi_id, int *apic_id) { struct acpi_madt_local_sapic *lsapic = - (struct acpi_madt_local_sapic *)entry; + container_of(entry, struct acpi_madt_local_sapic, header); if (!(lsapic->lapic_flags & ACPI_MADT_ENABLED)) return -ENODEV; diff --git a/drivers/acpi/sbs.c b/drivers/acpi/sbs.c index 366ca40a6f70..a7a3edd28beb 100644 --- a/drivers/acpi/sbs.c +++ b/drivers/acpi/sbs.c @@ -35,6 +35,7 @@ #include <linux/jiffies.h> #include <linux/delay.h> #include <linux/power_supply.h> +#include <linux/dmi.h> #include "sbshc.h" #include "battery.h" @@ -61,6 +62,8 @@ static unsigned int cache_time = 1000; module_param(cache_time, uint, 0644); MODULE_PARM_DESC(cache_time, "cache time in milliseconds"); +static bool sbs_manager_broken; + #define MAX_SBS_BAT 4 #define ACPI_SBS_BLOCK_MAX 32 @@ -109,6 +112,7 @@ struct acpi_sbs { u8 batteries_supported:4; u8 manager_present:1; u8 charger_present:1; + u8 charger_exists:1; }; #define to_acpi_sbs(x) container_of(x, struct acpi_sbs, charger) @@ -429,9 +433,19 @@ static int acpi_ac_get_present(struct acpi_sbs *sbs) result = acpi_smbus_read(sbs->hc, SMBUS_READ_WORD, ACPI_SBS_CHARGER, 0x13, (u8 *) & status); - if (!result) - sbs->charger_present = (status >> 15) & 0x1; - return result; + + if (result) + return result; + + /* + * The spec requires that bit 4 always be 1. If it's not set, assume + * that the implementation doesn't support an SBS charger + */ + if (!((status >> 4) & 0x1)) + return -ENODEV; + + sbs->charger_present = (status >> 15) & 0x1; + return 0; } static ssize_t acpi_battery_alarm_show(struct device *dev, @@ -483,16 +497,21 @@ static int acpi_battery_read(struct acpi_battery *battery) ACPI_SBS_MANAGER, 0x01, (u8 *)&state, 2); } else if (battery->id == 0) battery->present = 1; + if (result || !battery->present) return result; if (saved_present != battery->present) { battery->update_time = 0; result = acpi_battery_get_info(battery); - if (result) + if (result) { + battery->present = 0; return result; + } } result = acpi_battery_get_state(battery); + if (result) + battery->present = 0; return result; } @@ -524,6 +543,7 @@ static int acpi_battery_add(struct acpi_sbs *sbs, int id) result = power_supply_register(&sbs->device->dev, &battery->bat); if (result) goto end; + result = device_create_file(battery->bat.dev, &alarm_attr); if (result) goto end; @@ -554,6 +574,7 @@ static int acpi_charger_add(struct acpi_sbs *sbs) if (result) goto end; + sbs->charger_exists = 1; sbs->charger.name = "sbs-charger"; sbs->charger.type = POWER_SUPPLY_TYPE_MAINS; sbs->charger.properties = sbs_ac_props; @@ -580,9 +601,12 @@ static void acpi_sbs_callback(void *context) struct acpi_battery *bat; u8 saved_charger_state = sbs->charger_present; u8 saved_battery_state; - acpi_ac_get_present(sbs); - if (sbs->charger_present != saved_charger_state) - kobject_uevent(&sbs->charger.dev->kobj, KOBJ_CHANGE); + + if (sbs->charger_exists) { + acpi_ac_get_present(sbs); + if (sbs->charger_present != saved_charger_state) + kobject_uevent(&sbs->charger.dev->kobj, KOBJ_CHANGE); + } if (sbs->manager_present) { for (id = 0; id < MAX_SBS_BAT; ++id) { @@ -598,12 +622,31 @@ static void acpi_sbs_callback(void *context) } } +static int disable_sbs_manager(const struct dmi_system_id *d) +{ + sbs_manager_broken = true; + return 0; +} + +static struct dmi_system_id acpi_sbs_dmi_table[] = { + { + .callback = disable_sbs_manager, + .ident = "Apple", + .matches = { + DMI_MATCH(DMI_SYS_VENDOR, "Apple Inc.") + }, + }, + { }, +}; + static int acpi_sbs_add(struct acpi_device *device) { struct acpi_sbs *sbs; int result = 0; int id; + dmi_check_system(acpi_sbs_dmi_table); + sbs = kzalloc(sizeof(struct acpi_sbs), GFP_KERNEL); if (!sbs) { result = -ENOMEM; @@ -619,17 +662,24 @@ static int acpi_sbs_add(struct acpi_device *device) device->driver_data = sbs; result = acpi_charger_add(sbs); - if (result) + if (result && result != -ENODEV) goto end; - result = acpi_manager_get_info(sbs); - if (!result) { - sbs->manager_present = 1; - for (id = 0; id < MAX_SBS_BAT; ++id) - if ((sbs->batteries_supported & (1 << id))) - acpi_battery_add(sbs, id); - } else + result = 0; + + if (!sbs_manager_broken) { + result = acpi_manager_get_info(sbs); + if (!result) { + sbs->manager_present = 0; + for (id = 0; id < MAX_SBS_BAT; ++id) + if ((sbs->batteries_supported & (1 << id))) + acpi_battery_add(sbs, id); + } + } + + if (!sbs->manager_present) acpi_battery_add(sbs, 0); + acpi_smbus_register_callback(sbs->hc, acpi_sbs_callback, sbs); end: if (result) diff --git a/drivers/acpi/sleep.c b/drivers/acpi/sleep.c index 54da4a3fe65e..05a31b573fc3 100644 --- a/drivers/acpi/sleep.c +++ b/drivers/acpi/sleep.c @@ -14,6 +14,7 @@ #include <linux/irq.h> #include <linux/dmi.h> #include <linux/device.h> +#include <linux/interrupt.h> #include <linux/suspend.h> #include <linux/reboot.h> #include <linux/acpi.h> @@ -626,6 +627,19 @@ static int acpi_freeze_begin(void) return 0; } +static int acpi_freeze_prepare(void) +{ + acpi_enable_all_wakeup_gpes(); + enable_irq_wake(acpi_gbl_FADT.sci_interrupt); + return 0; +} + +static void acpi_freeze_restore(void) +{ + disable_irq_wake(acpi_gbl_FADT.sci_interrupt); + acpi_enable_all_runtime_gpes(); +} + static void acpi_freeze_end(void) { acpi_scan_lock_release(); @@ -633,6 +647,8 @@ static void acpi_freeze_end(void) static const struct platform_freeze_ops acpi_freeze_ops = { .begin = acpi_freeze_begin, + .prepare = acpi_freeze_prepare, + .restore = acpi_freeze_restore, .end = acpi_freeze_end, }; diff --git a/drivers/acpi/utils.c b/drivers/acpi/utils.c index 07c8c5a5ee95..834f35c4bf8d 100644 --- a/drivers/acpi/utils.c +++ b/drivers/acpi/utils.c @@ -661,7 +661,6 @@ EXPORT_SYMBOL(acpi_evaluate_dsm); * @uuid: UUID of requested functions, should be 16 bytes at least * @rev: revision number of requested functions * @funcs: bitmap of requested functions - * @exclude: excluding special value, used to support i915 and nouveau * * Evaluate device's _DSM method to check whether it supports requested * functions. Currently only support 64 functions at maximum, should be diff --git a/drivers/acpi/video.c b/drivers/acpi/video.c index 8e7e18567ae6..807a88a0f394 100644 --- a/drivers/acpi/video.c +++ b/drivers/acpi/video.c @@ -411,12 +411,6 @@ static int __init video_set_bqc_offset(const struct dmi_system_id *d) return 0; } -static int __init video_set_use_native_backlight(const struct dmi_system_id *d) -{ - use_native_backlight_dmi = true; - return 0; -} - static int __init video_disable_native_backlight(const struct dmi_system_id *d) { use_native_backlight_dmi = false; @@ -467,265 +461,6 @@ static struct dmi_system_id video_dmi_table[] __initdata = { DMI_MATCH(DMI_PRODUCT_NAME, "Aspire 7720"), }, }, - { - .callback = video_set_use_native_backlight, - .ident = "ThinkPad X230", - .matches = { - DMI_MATCH(DMI_SYS_VENDOR, "LENOVO"), - DMI_MATCH(DMI_PRODUCT_VERSION, "ThinkPad X230"), - }, - }, - { - .callback = video_set_use_native_backlight, - .ident = "ThinkPad T430 and T430s", - .matches = { - DMI_MATCH(DMI_SYS_VENDOR, "LENOVO"), - DMI_MATCH(DMI_PRODUCT_VERSION, "ThinkPad T430"), - }, - }, - { - .callback = video_set_use_native_backlight, - .ident = "ThinkPad T430", - .matches = { - DMI_MATCH(DMI_SYS_VENDOR, "LENOVO"), - DMI_MATCH(DMI_PRODUCT_VERSION, "2349D15"), - }, - }, - { - .callback = video_set_use_native_backlight, - .ident = "ThinkPad T431s", - .matches = { - DMI_MATCH(DMI_SYS_VENDOR, "LENOVO"), - DMI_MATCH(DMI_PRODUCT_VERSION, "20AACTO1WW"), - }, - }, - { - .callback = video_set_use_native_backlight, - .ident = "ThinkPad Edge E530", - .matches = { - DMI_MATCH(DMI_SYS_VENDOR, "LENOVO"), - DMI_MATCH(DMI_PRODUCT_VERSION, "3259A2G"), - }, - }, - { - .callback = video_set_use_native_backlight, - .ident = "ThinkPad Edge E530", - .matches = { - DMI_MATCH(DMI_SYS_VENDOR, "LENOVO"), - DMI_MATCH(DMI_PRODUCT_VERSION, "3259CTO"), - }, - }, - { - .callback = video_set_use_native_backlight, - .ident = "ThinkPad Edge E530", - .matches = { - DMI_MATCH(DMI_SYS_VENDOR, "LENOVO"), - DMI_MATCH(DMI_PRODUCT_VERSION, "3259HJG"), - }, - }, - { - .callback = video_set_use_native_backlight, - .ident = "ThinkPad W530", - .matches = { - DMI_MATCH(DMI_SYS_VENDOR, "LENOVO"), - DMI_MATCH(DMI_PRODUCT_VERSION, "ThinkPad W530"), - }, - }, - { - .callback = video_set_use_native_backlight, - .ident = "ThinkPad X1 Carbon", - .matches = { - DMI_MATCH(DMI_SYS_VENDOR, "LENOVO"), - DMI_MATCH(DMI_PRODUCT_VERSION, "ThinkPad X1 Carbon"), - }, - }, - { - .callback = video_set_use_native_backlight, - .ident = "Lenovo Yoga 13", - .matches = { - DMI_MATCH(DMI_SYS_VENDOR, "LENOVO"), - DMI_MATCH(DMI_PRODUCT_VERSION, "Lenovo IdeaPad Yoga 13"), - }, - }, - { - .callback = video_set_use_native_backlight, - .ident = "Lenovo Yoga 2 11", - .matches = { - DMI_MATCH(DMI_SYS_VENDOR, "LENOVO"), - DMI_MATCH(DMI_PRODUCT_VERSION, "Lenovo Yoga 2 11"), - }, - }, - { - .callback = video_set_use_native_backlight, - .ident = "Thinkpad Helix", - .matches = { - DMI_MATCH(DMI_SYS_VENDOR, "LENOVO"), - DMI_MATCH(DMI_PRODUCT_VERSION, "ThinkPad Helix"), - }, - }, - { - .callback = video_set_use_native_backlight, - .ident = "Dell Inspiron 7520", - .matches = { - DMI_MATCH(DMI_SYS_VENDOR, "Dell Inc."), - DMI_MATCH(DMI_PRODUCT_NAME, "Inspiron 7520"), - }, - }, - { - .callback = video_set_use_native_backlight, - .ident = "Acer Aspire 5733Z", - .matches = { - DMI_MATCH(DMI_SYS_VENDOR, "Acer"), - DMI_MATCH(DMI_PRODUCT_NAME, "Aspire 5733Z"), - }, - }, - { - .callback = video_set_use_native_backlight, - .ident = "Acer Aspire 5742G", - .matches = { - DMI_MATCH(DMI_SYS_VENDOR, "Acer"), - DMI_MATCH(DMI_PRODUCT_NAME, "Aspire 5742G"), - }, - }, - { - .callback = video_set_use_native_backlight, - .ident = "Acer Aspire V5-171", - .matches = { - DMI_MATCH(DMI_SYS_VENDOR, "Acer"), - DMI_MATCH(DMI_PRODUCT_NAME, "V5-171"), - }, - }, - { - .callback = video_set_use_native_backlight, - .ident = "Acer Aspire V5-431", - .matches = { - DMI_MATCH(DMI_SYS_VENDOR, "Acer"), - DMI_MATCH(DMI_PRODUCT_NAME, "Aspire V5-431"), - }, - }, - { - .callback = video_set_use_native_backlight, - .ident = "Acer Aspire V5-471G", - .matches = { - DMI_MATCH(DMI_BOARD_VENDOR, "Acer"), - DMI_MATCH(DMI_PRODUCT_NAME, "Aspire V5-471G"), - }, - }, - { - .callback = video_set_use_native_backlight, - .ident = "Acer TravelMate B113", - .matches = { - DMI_MATCH(DMI_SYS_VENDOR, "Acer"), - DMI_MATCH(DMI_PRODUCT_NAME, "TravelMate B113"), - }, - }, - { - .callback = video_set_use_native_backlight, - .ident = "Acer Aspire V5-572G", - .matches = { - DMI_MATCH(DMI_SYS_VENDOR, "Acer Aspire"), - DMI_MATCH(DMI_PRODUCT_VERSION, "V5-572G/Dazzle_CX"), - }, - }, - { - .callback = video_set_use_native_backlight, - .ident = "Acer Aspire V5-573G", - .matches = { - DMI_MATCH(DMI_SYS_VENDOR, "Acer Aspire"), - DMI_MATCH(DMI_PRODUCT_VERSION, "V5-573G/Dazzle_HW"), - }, - }, - { - .callback = video_set_use_native_backlight, - .ident = "ASUS Zenbook Prime UX31A", - .matches = { - DMI_MATCH(DMI_SYS_VENDOR, "ASUSTeK COMPUTER INC."), - DMI_MATCH(DMI_PRODUCT_NAME, "UX31A"), - }, - }, - { - .callback = video_set_use_native_backlight, - .ident = "HP ProBook 4340s", - .matches = { - DMI_MATCH(DMI_SYS_VENDOR, "Hewlett-Packard"), - DMI_MATCH(DMI_PRODUCT_VERSION, "HP ProBook 4340s"), - }, - }, - { - .callback = video_set_use_native_backlight, - .ident = "HP ProBook 4540s", - .matches = { - DMI_MATCH(DMI_SYS_VENDOR, "Hewlett-Packard"), - DMI_MATCH(DMI_PRODUCT_VERSION, "HP ProBook 4540s"), - }, - }, - { - .callback = video_set_use_native_backlight, - .ident = "HP ProBook 2013 models", - .matches = { - DMI_MATCH(DMI_SYS_VENDOR, "Hewlett-Packard"), - DMI_MATCH(DMI_PRODUCT_NAME, "HP ProBook "), - DMI_MATCH(DMI_PRODUCT_NAME, " G1"), - }, - }, - { - .callback = video_set_use_native_backlight, - .ident = "HP EliteBook 2013 models", - .matches = { - DMI_MATCH(DMI_SYS_VENDOR, "Hewlett-Packard"), - DMI_MATCH(DMI_PRODUCT_NAME, "HP EliteBook "), - DMI_MATCH(DMI_PRODUCT_NAME, " G1"), - }, - }, - { - .callback = video_set_use_native_backlight, - .ident = "HP EliteBook 2014 models", - .matches = { - DMI_MATCH(DMI_SYS_VENDOR, "Hewlett-Packard"), - DMI_MATCH(DMI_PRODUCT_NAME, "HP EliteBook "), - DMI_MATCH(DMI_PRODUCT_NAME, " G2"), - }, - }, - { - .callback = video_set_use_native_backlight, - .ident = "HP ZBook 14", - .matches = { - DMI_MATCH(DMI_SYS_VENDOR, "Hewlett-Packard"), - DMI_MATCH(DMI_PRODUCT_NAME, "HP ZBook 14"), - }, - }, - { - .callback = video_set_use_native_backlight, - .ident = "HP ZBook 15", - .matches = { - DMI_MATCH(DMI_SYS_VENDOR, "Hewlett-Packard"), - DMI_MATCH(DMI_PRODUCT_NAME, "HP ZBook 15"), - }, - }, - { - .callback = video_set_use_native_backlight, - .ident = "HP ZBook 17", - .matches = { - DMI_MATCH(DMI_SYS_VENDOR, "Hewlett-Packard"), - DMI_MATCH(DMI_PRODUCT_NAME, "HP ZBook 17"), - }, - }, - { - .callback = video_set_use_native_backlight, - .ident = "HP EliteBook 8470p", - .matches = { - DMI_MATCH(DMI_SYS_VENDOR, "Hewlett-Packard"), - DMI_MATCH(DMI_PRODUCT_NAME, "HP EliteBook 8470p"), - }, - }, - { - .callback = video_set_use_native_backlight, - .ident = "HP EliteBook 8780w", - .matches = { - DMI_MATCH(DMI_SYS_VENDOR, "Hewlett-Packard"), - DMI_MATCH(DMI_PRODUCT_NAME, "HP EliteBook 8780w"), - }, - }, /* * These models have a working acpi_video backlight control, and using @@ -1419,6 +1154,23 @@ acpi_video_device_bind(struct acpi_video_bus *video, } } +static bool acpi_video_device_in_dod(struct acpi_video_device *device) +{ + struct acpi_video_bus *video = device->video; + int i; + + /* If we have a broken _DOD, no need to test */ + if (!video->attached_count) + return true; + + for (i = 0; i < video->attached_count; i++) { + if (video->attached_array[i].bind_info == device) + return true; + } + + return false; +} + /* * Arg: * video : video bus device @@ -1858,6 +1610,15 @@ static void acpi_video_dev_register_backlight(struct acpi_video_device *device) static int count; char *name; + /* + * Do not create backlight device for video output + * device that is not in the enumerated list. + */ + if (!acpi_video_device_in_dod(device)) { + dev_dbg(&device->dev->dev, "not in _DOD list, ignore\n"); + return; + } + result = acpi_video_init_brightness(device); if (result) return; diff --git a/drivers/acpi/video_detect.c b/drivers/acpi/video_detect.c index c42feb2bacd0..27c43499977a 100644 --- a/drivers/acpi/video_detect.c +++ b/drivers/acpi/video_detect.c @@ -174,6 +174,14 @@ static struct dmi_system_id video_detect_dmi_table[] = { DMI_MATCH(DMI_PRODUCT_NAME, "Inspiron 5737"), }, }, + { + .callback = video_detect_force_vendor, + .ident = "Lenovo IdeaPad Z570", + .matches = { + DMI_MATCH(DMI_SYS_VENDOR, "LENOVO"), + DMI_MATCH(DMI_PRODUCT_VERSION, "Ideapad Z570"), + }, + }, { }, }; |