diff options
Diffstat (limited to 'drivers/acpi')
-rw-r--r-- | drivers/acpi/acpi_lpss.c | 168 | ||||
-rw-r--r-- | drivers/acpi/acpi_pnp.c | 6 | ||||
-rw-r--r-- | drivers/acpi/acpica/aclocal.h | 1 | ||||
-rw-r--r-- | drivers/acpi/acpica/acobject.h | 1 | ||||
-rw-r--r-- | drivers/acpi/acpica/dsfield.c | 2 | ||||
-rw-r--r-- | drivers/acpi/acpica/evregion.c | 47 | ||||
-rw-r--r-- | drivers/acpi/acpica/evxfgpe.c | 32 | ||||
-rw-r--r-- | drivers/acpi/acpica/exfield.c | 67 | ||||
-rw-r--r-- | drivers/acpi/acpica/exprep.c | 2 | ||||
-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/bus.c | 10 | ||||
-rw-r--r-- | drivers/acpi/container.c | 8 | ||||
-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/scan.c | 5 | ||||
-rw-r--r-- | drivers/acpi/sleep.c | 16 | ||||
-rw-r--r-- | drivers/acpi/utils.c | 1 | ||||
-rw-r--r-- | drivers/acpi/video.c | 299 | ||||
-rw-r--r-- | drivers/acpi/video_detect.c | 8 |
26 files changed, 443 insertions, 481 deletions
diff --git a/drivers/acpi/acpi_lpss.c b/drivers/acpi/acpi_lpss.c index fddc1e86f9d0..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,13 +365,9 @@ 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)) { - device_enable_async_suspend(&pdev->dev); return 1; } @@ -693,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; @@ -722,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 996fa1959eea..b193f8425999 100644 --- a/drivers/acpi/acpi_pnp.c +++ b/drivers/acpi/acpi_pnp.c @@ -15,8 +15,6 @@ #include <linux/ctype.h> static const struct acpi_device_id acpi_pnp_device_ids[] = { - /* soc_button_array */ - {"PNP0C40"}, /* pata_isapnp */ {"PNP0600"}, /* Generic ESDI/IDE/ATA compatible hard disk controller */ /* floppy */ @@ -132,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/aclocal.h b/drivers/acpi/acpica/aclocal.h index 1f9aba5fb81f..2747279fbe3c 100644 --- a/drivers/acpi/acpica/aclocal.h +++ b/drivers/acpi/acpica/aclocal.h @@ -254,6 +254,7 @@ struct acpi_create_field_info { u32 field_bit_position; u32 field_bit_length; u16 resource_length; + u16 pin_number_index; u8 field_flags; u8 attribute; u8 field_type; diff --git a/drivers/acpi/acpica/acobject.h b/drivers/acpi/acpica/acobject.h index 22fb6449d3d6..8abb393dafab 100644 --- a/drivers/acpi/acpica/acobject.h +++ b/drivers/acpi/acpica/acobject.h @@ -264,6 +264,7 @@ struct acpi_object_region_field { ACPI_OBJECT_COMMON_HEADER ACPI_COMMON_FIELD_INFO u16 resource_length; union acpi_operand_object *region_obj; /* Containing op_region object */ u8 *resource_buffer; /* resource_template for serial regions/fields */ + u16 pin_number_index; /* Index relative to previous Connection/Template */ }; struct acpi_object_bank_field { diff --git a/drivers/acpi/acpica/dsfield.c b/drivers/acpi/acpica/dsfield.c index 3661c8e90540..c57666196672 100644 --- a/drivers/acpi/acpica/dsfield.c +++ b/drivers/acpi/acpica/dsfield.c @@ -360,6 +360,7 @@ acpi_ds_get_field_names(struct acpi_create_field_info *info, */ info->resource_buffer = NULL; info->connection_node = NULL; + info->pin_number_index = 0; /* * A Connection() is either an actual resource descriptor (buffer) @@ -437,6 +438,7 @@ acpi_ds_get_field_names(struct acpi_create_field_info *info, } info->field_bit_position += info->field_bit_length; + info->pin_number_index++; /* Index relative to previous Connection() */ break; default: diff --git a/drivers/acpi/acpica/evregion.c b/drivers/acpi/acpica/evregion.c index 9957297d1580..8eb8575e8c16 100644 --- a/drivers/acpi/acpica/evregion.c +++ b/drivers/acpi/acpica/evregion.c @@ -142,6 +142,7 @@ acpi_ev_address_space_dispatch(union acpi_operand_object *region_obj, union acpi_operand_object *region_obj2; void *region_context = NULL; struct acpi_connection_info *context; + acpi_physical_address address; ACPI_FUNCTION_TRACE(ev_address_space_dispatch); @@ -231,25 +232,23 @@ acpi_ev_address_space_dispatch(union acpi_operand_object *region_obj, /* We have everything we need, we can invoke the address space handler */ handler = handler_desc->address_space.handler; - - ACPI_DEBUG_PRINT((ACPI_DB_OPREGION, - "Handler %p (@%p) Address %8.8X%8.8X [%s]\n", - ®ion_obj->region.handler->address_space, handler, - ACPI_FORMAT_NATIVE_UINT(region_obj->region.address + - region_offset), - acpi_ut_get_region_name(region_obj->region. - space_id))); + address = (region_obj->region.address + region_offset); /* * Special handling for generic_serial_bus and general_purpose_io: * There are three extra parameters that must be passed to the * handler via the context: - * 1) Connection buffer, a resource template from Connection() op. - * 2) Length of the above buffer. - * 3) Actual access length from the access_as() op. + * 1) Connection buffer, a resource template from Connection() op + * 2) Length of the above buffer + * 3) Actual access length from the access_as() op + * + * In addition, for general_purpose_io, the Address and bit_width fields + * are defined as follows: + * 1) Address is the pin number index of the field (bit offset from + * the previous Connection) + * 2) bit_width is the actual bit length of the field (number of pins) */ - if (((region_obj->region.space_id == ACPI_ADR_SPACE_GSBUS) || - (region_obj->region.space_id == ACPI_ADR_SPACE_GPIO)) && + if ((region_obj->region.space_id == ACPI_ADR_SPACE_GSBUS) && context && field_obj) { /* Get the Connection (resource_template) buffer */ @@ -258,6 +257,24 @@ acpi_ev_address_space_dispatch(union acpi_operand_object *region_obj, context->length = field_obj->field.resource_length; context->access_length = field_obj->field.access_length; } + if ((region_obj->region.space_id == ACPI_ADR_SPACE_GPIO) && + context && field_obj) { + + /* Get the Connection (resource_template) buffer */ + + context->connection = field_obj->field.resource_buffer; + context->length = field_obj->field.resource_length; + context->access_length = field_obj->field.access_length; + address = field_obj->field.pin_number_index; + bit_width = field_obj->field.bit_length; + } + + ACPI_DEBUG_PRINT((ACPI_DB_OPREGION, + "Handler %p (@%p) Address %8.8X%8.8X [%s]\n", + ®ion_obj->region.handler->address_space, handler, + ACPI_FORMAT_NATIVE_UINT(address), + acpi_ut_get_region_name(region_obj->region. + space_id))); if (!(handler_desc->address_space.handler_flags & ACPI_ADDR_HANDLER_DEFAULT_INSTALLED)) { @@ -271,9 +288,7 @@ acpi_ev_address_space_dispatch(union acpi_operand_object *region_obj, /* Call the handler */ - status = handler(function, - (region_obj->region.address + region_offset), - bit_width, value, context, + status = handler(function, address, bit_width, value, context, region_obj2->extra.region_context); if (ACPI_FAILURE(status)) { 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/exfield.c b/drivers/acpi/acpica/exfield.c index 6907ce0c704c..b994845ed359 100644 --- a/drivers/acpi/acpica/exfield.c +++ b/drivers/acpi/acpica/exfield.c @@ -253,6 +253,37 @@ acpi_ex_read_data_from_field(struct acpi_walk_state * walk_state, buffer = &buffer_desc->integer.value; } + if ((obj_desc->common.type == ACPI_TYPE_LOCAL_REGION_FIELD) && + (obj_desc->field.region_obj->region.space_id == + ACPI_ADR_SPACE_GPIO)) { + /* + * For GPIO (general_purpose_io), the Address will be the bit offset + * from the previous Connection() operator, making it effectively a + * pin number index. The bit_length is the length of the field, which + * is thus the number of pins. + */ + ACPI_DEBUG_PRINT((ACPI_DB_BFIELD, + "GPIO FieldRead [FROM]: Pin %u Bits %u\n", + obj_desc->field.pin_number_index, + obj_desc->field.bit_length)); + + /* Lock entire transaction if requested */ + + acpi_ex_acquire_global_lock(obj_desc->common_field.field_flags); + + /* Perform the write */ + + status = acpi_ex_access_region(obj_desc, 0, + (u64 *)buffer, ACPI_READ); + acpi_ex_release_global_lock(obj_desc->common_field.field_flags); + if (ACPI_FAILURE(status)) { + acpi_ut_remove_reference(buffer_desc); + } else { + *ret_buffer_desc = buffer_desc; + } + return_ACPI_STATUS(status); + } + ACPI_DEBUG_PRINT((ACPI_DB_BFIELD, "FieldRead [TO]: Obj %p, Type %X, Buf %p, ByteLen %X\n", obj_desc, obj_desc->common.type, buffer, @@ -413,6 +444,42 @@ acpi_ex_write_data_to_field(union acpi_operand_object *source_desc, *result_desc = buffer_desc; return_ACPI_STATUS(status); + } else if ((obj_desc->common.type == ACPI_TYPE_LOCAL_REGION_FIELD) && + (obj_desc->field.region_obj->region.space_id == + ACPI_ADR_SPACE_GPIO)) { + /* + * For GPIO (general_purpose_io), we will bypass the entire field + * mechanism and handoff the bit address and bit width directly to + * the handler. The Address will be the bit offset + * from the previous Connection() operator, making it effectively a + * pin number index. The bit_length is the length of the field, which + * is thus the number of pins. + */ + if (source_desc->common.type != ACPI_TYPE_INTEGER) { + return_ACPI_STATUS(AE_AML_OPERAND_TYPE); + } + + ACPI_DEBUG_PRINT((ACPI_DB_BFIELD, + "GPIO FieldWrite [FROM]: (%s:%X), Val %.8X [TO]: Pin %u Bits %u\n", + acpi_ut_get_type_name(source_desc->common. + type), + source_desc->common.type, + (u32)source_desc->integer.value, + obj_desc->field.pin_number_index, + obj_desc->field.bit_length)); + + buffer = &source_desc->integer.value; + + /* Lock entire transaction if requested */ + + acpi_ex_acquire_global_lock(obj_desc->common_field.field_flags); + + /* Perform the write */ + + status = acpi_ex_access_region(obj_desc, 0, + (u64 *)buffer, ACPI_WRITE); + acpi_ex_release_global_lock(obj_desc->common_field.field_flags); + return_ACPI_STATUS(status); } /* Get a pointer to the data to be written */ diff --git a/drivers/acpi/acpica/exprep.c b/drivers/acpi/acpica/exprep.c index ee3f872870bc..118e942005e5 100644 --- a/drivers/acpi/acpica/exprep.c +++ b/drivers/acpi/acpica/exprep.c @@ -484,6 +484,8 @@ acpi_status acpi_ex_prep_field_value(struct acpi_create_field_info *info) obj_desc->field.resource_length = info->resource_length; } + obj_desc->field.pin_number_index = info->pin_number_index; + /* Allow full data read from EC address space */ if ((obj_desc->field.region_obj->region.space_id == 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/bus.c b/drivers/acpi/bus.c index 8581f5b84f48..8b67bd0f6bb5 100644 --- a/drivers/acpi/bus.c +++ b/drivers/acpi/bus.c @@ -177,16 +177,6 @@ void acpi_bus_detach_private_data(acpi_handle handle) } EXPORT_SYMBOL_GPL(acpi_bus_detach_private_data); -void acpi_bus_no_hotplug(acpi_handle handle) -{ - struct acpi_device *adev = NULL; - - acpi_bus_get_device(handle, &adev); - if (adev) - adev->flags.no_hotplug = true; -} -EXPORT_SYMBOL_GPL(acpi_bus_no_hotplug); - static void acpi_print_osc_error(acpi_handle handle, struct acpi_osc_context *context, char *error) { diff --git a/drivers/acpi/container.c b/drivers/acpi/container.c index 76f7cff64594..c8ead9f97375 100644 --- a/drivers/acpi/container.c +++ b/drivers/acpi/container.c @@ -99,6 +99,13 @@ static void container_device_detach(struct acpi_device *adev) device_unregister(dev); } +static void container_device_online(struct acpi_device *adev) +{ + struct device *dev = acpi_driver_data(adev); + + kobject_uevent(&dev->kobj, KOBJ_ONLINE); +} + static struct acpi_scan_handler container_handler = { .ids = container_device_ids, .attach = container_device_attach, @@ -106,6 +113,7 @@ static struct acpi_scan_handler container_handler = { .hotplug = { .enabled = true, .demand_offline = true, + .notify_online = container_device_online, }, }; 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/scan.c b/drivers/acpi/scan.c index 3bf7764659a4..ae44d8654c82 100644 --- a/drivers/acpi/scan.c +++ b/drivers/acpi/scan.c @@ -130,7 +130,7 @@ static int create_modalias(struct acpi_device *acpi_dev, char *modalias, list_for_each_entry(id, &acpi_dev->pnp.ids, list) { count = snprintf(&modalias[len], size, "%s:", id->id); if (count < 0) - return EINVAL; + return -EINVAL; if (count >= size) return -ENOMEM; len += count; @@ -2189,6 +2189,9 @@ static void acpi_bus_attach(struct acpi_device *device) ok: list_for_each_entry(child, &device->children, node) acpi_bus_attach(child); + + if (device->handler && device->handler->hotplug.notify_online) + device->handler->hotplug.notify_online(device); } /** 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 fcbda105616e..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 @@ -750,6 +485,14 @@ static struct dmi_system_id video_dmi_table[] __initdata = { DMI_MATCH(DMI_PRODUCT_VERSION, "ThinkPad T520"), }, }, + { + .callback = video_disable_native_backlight, + .ident = "ThinkPad X201s", + .matches = { + DMI_MATCH(DMI_SYS_VENDOR, "LENOVO"), + DMI_MATCH(DMI_PRODUCT_VERSION, "ThinkPad X201s"), + }, + }, /* The native backlight controls do not work on some older machines */ { @@ -1411,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 @@ -1850,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"), + }, + }, { }, }; |