Merge branches 'acpi-power', 'acpi-blacklist', 'acpi-video' and 'acpi-doc'
* acpi-power: power: supply: axp288_charger: Only wait for INT3496 device if present ACPI / AC: Add a blacklist with PMIC ACPI HIDs with a native charger driver ACPI / battery: Add a blacklist with PMIC ACPI HIDs with a native battery driver ACPI / battery: Fix acpi_battery_exit on acpi_battery_init_async errors ACPI / utils: Add new acpi_dev_present helper * acpi-blacklist: ACPI / blacklist: add _REV quirk for Dell Inspiron 7537 * acpi-video: ACPI / video: add comments about subtle cases ACPI / video: get rid of magic numbers and use enum instead * acpi-doc: ACPI / doc: linuxized-acpica.txt: fix typos
This commit is contained in:
commit
52e70c8af7
9 changed files with 254 additions and 63 deletions
|
@ -24,7 +24,7 @@ upstream.
|
||||||
The homepage of ACPICA project is: www.acpica.org, it is maintained and
|
The homepage of ACPICA project is: www.acpica.org, it is maintained and
|
||||||
supported by Intel Corporation.
|
supported by Intel Corporation.
|
||||||
|
|
||||||
The following figure depicts the Linux ACPI subystem where the ACPICA
|
The following figure depicts the Linux ACPI subsystem where the ACPICA
|
||||||
adaptation is included:
|
adaptation is included:
|
||||||
|
|
||||||
+---------------------------------------------------------+
|
+---------------------------------------------------------+
|
||||||
|
@ -110,7 +110,7 @@ upstream.
|
||||||
Linux patches. The patches generated by this process are referred to as
|
Linux patches. The patches generated by this process are referred to as
|
||||||
"linuxized ACPICA patches". The release process is carried out on a local
|
"linuxized ACPICA patches". The release process is carried out on a local
|
||||||
copy the ACPICA git repository. Each commit in the monthly release is
|
copy the ACPICA git repository. Each commit in the monthly release is
|
||||||
converted into a linuxized ACPICA patch. Together, they form the montly
|
converted into a linuxized ACPICA patch. Together, they form the monthly
|
||||||
ACPICA release patchset for the Linux ACPI community. This process is
|
ACPICA release patchset for the Linux ACPI community. This process is
|
||||||
illustrated in the following figure:
|
illustrated in the following figure:
|
||||||
|
|
||||||
|
@ -165,7 +165,7 @@ upstream.
|
||||||
<http://git.kernel.org/pub/scm/linux/kernel/git/torvalds/linux.git>.
|
<http://git.kernel.org/pub/scm/linux/kernel/git/torvalds/linux.git>.
|
||||||
|
|
||||||
Before the linuxized ACPICA patches are sent to the Linux ACPI community
|
Before the linuxized ACPICA patches are sent to the Linux ACPI community
|
||||||
for review, there is a quality ensurance build test process to reduce
|
for review, there is a quality assurance build test process to reduce
|
||||||
porting issues. Currently this build process only takes care of the
|
porting issues. Currently this build process only takes care of the
|
||||||
following kernel configuration options:
|
following kernel configuration options:
|
||||||
CONFIG_ACPI/CONFIG_ACPI_DEBUG/CONFIG_ACPI_DEBUGGER
|
CONFIG_ACPI/CONFIG_ACPI_DEBUG/CONFIG_ACPI_DEBUGGER
|
||||||
|
@ -195,12 +195,12 @@ upstream.
|
||||||
release utilities (please refer to Section 4 below for the details).
|
release utilities (please refer to Section 4 below for the details).
|
||||||
3. Linux specific features - Sometimes it's impossible to use the
|
3. Linux specific features - Sometimes it's impossible to use the
|
||||||
current ACPICA APIs to implement features required by the Linux kernel,
|
current ACPICA APIs to implement features required by the Linux kernel,
|
||||||
so Linux developers occasionaly have to change ACPICA code directly.
|
so Linux developers occasionally have to change ACPICA code directly.
|
||||||
Those changes may not be acceptable by ACPICA upstream and in such cases
|
Those changes may not be acceptable by ACPICA upstream and in such cases
|
||||||
they are left as committed ACPICA divergences unless the ACPICA side can
|
they are left as committed ACPICA divergences unless the ACPICA side can
|
||||||
implement new mechanisms as replacements for them.
|
implement new mechanisms as replacements for them.
|
||||||
4. ACPICA release fixups - ACPICA only tests commits using a set of the
|
4. ACPICA release fixups - ACPICA only tests commits using a set of the
|
||||||
user space simulation utilies, thus the linuxized ACPICA patches may
|
user space simulation utilities, thus the linuxized ACPICA patches may
|
||||||
break the Linux kernel, leaving us build/boot failures. In order to
|
break the Linux kernel, leaving us build/boot failures. In order to
|
||||||
avoid breaking Linux bisection, fixes are applied directly to the
|
avoid breaking Linux bisection, fixes are applied directly to the
|
||||||
linuxized ACPICA patches during the release process. When the release
|
linuxized ACPICA patches during the release process. When the release
|
||||||
|
|
|
@ -57,12 +57,23 @@ static int acpi_ac_add(struct acpi_device *device);
|
||||||
static int acpi_ac_remove(struct acpi_device *device);
|
static int acpi_ac_remove(struct acpi_device *device);
|
||||||
static void acpi_ac_notify(struct acpi_device *device, u32 event);
|
static void acpi_ac_notify(struct acpi_device *device, u32 event);
|
||||||
|
|
||||||
|
struct acpi_ac_bl {
|
||||||
|
const char *hid;
|
||||||
|
int hrv;
|
||||||
|
};
|
||||||
|
|
||||||
static const struct acpi_device_id ac_device_ids[] = {
|
static const struct acpi_device_id ac_device_ids[] = {
|
||||||
{"ACPI0003", 0},
|
{"ACPI0003", 0},
|
||||||
{"", 0},
|
{"", 0},
|
||||||
};
|
};
|
||||||
MODULE_DEVICE_TABLE(acpi, ac_device_ids);
|
MODULE_DEVICE_TABLE(acpi, ac_device_ids);
|
||||||
|
|
||||||
|
/* Lists of PMIC ACPI HIDs with an (often better) native charger driver */
|
||||||
|
static const struct acpi_ac_bl acpi_ac_blacklist[] = {
|
||||||
|
{ "INT33F4", -1 }, /* X-Powers AXP288 PMIC */
|
||||||
|
{ "INT34D3", 3 }, /* Intel Cherrytrail Whiskey Cove PMIC */
|
||||||
|
};
|
||||||
|
|
||||||
#ifdef CONFIG_PM_SLEEP
|
#ifdef CONFIG_PM_SLEEP
|
||||||
static int acpi_ac_resume(struct device *dev);
|
static int acpi_ac_resume(struct device *dev);
|
||||||
#endif
|
#endif
|
||||||
|
@ -424,11 +435,20 @@ static int acpi_ac_remove(struct acpi_device *device)
|
||||||
|
|
||||||
static int __init acpi_ac_init(void)
|
static int __init acpi_ac_init(void)
|
||||||
{
|
{
|
||||||
|
unsigned int i;
|
||||||
int result;
|
int result;
|
||||||
|
|
||||||
if (acpi_disabled)
|
if (acpi_disabled)
|
||||||
return -ENODEV;
|
return -ENODEV;
|
||||||
|
|
||||||
|
for (i = 0; i < ARRAY_SIZE(acpi_ac_blacklist); i++)
|
||||||
|
if (acpi_dev_present(acpi_ac_blacklist[i].hid, "1",
|
||||||
|
acpi_ac_blacklist[i].hrv)) {
|
||||||
|
pr_info(PREFIX "AC: found native %s PMIC, not loading\n",
|
||||||
|
acpi_ac_blacklist[i].hid);
|
||||||
|
return -ENODEV;
|
||||||
|
}
|
||||||
|
|
||||||
#ifdef CONFIG_ACPI_PROCFS_POWER
|
#ifdef CONFIG_ACPI_PROCFS_POWER
|
||||||
acpi_ac_dir = acpi_lock_ac_dir();
|
acpi_ac_dir = acpi_lock_ac_dir();
|
||||||
if (!acpi_ac_dir)
|
if (!acpi_ac_dir)
|
||||||
|
|
|
@ -73,6 +73,10 @@ module_param(report_key_events, int, 0644);
|
||||||
MODULE_PARM_DESC(report_key_events,
|
MODULE_PARM_DESC(report_key_events,
|
||||||
"0: none, 1: output changes, 2: brightness changes, 3: all");
|
"0: none, 1: output changes, 2: brightness changes, 3: all");
|
||||||
|
|
||||||
|
/*
|
||||||
|
* Whether the struct acpi_video_device_attrib::device_id_scheme bit should be
|
||||||
|
* assumed even if not actually set.
|
||||||
|
*/
|
||||||
static bool device_id_scheme = false;
|
static bool device_id_scheme = false;
|
||||||
module_param(device_id_scheme, bool, 0444);
|
module_param(device_id_scheme, bool, 0444);
|
||||||
|
|
||||||
|
@ -88,6 +92,18 @@ static int acpi_video_bus_remove(struct acpi_device *device);
|
||||||
static void acpi_video_bus_notify(struct acpi_device *device, u32 event);
|
static void acpi_video_bus_notify(struct acpi_device *device, u32 event);
|
||||||
void acpi_video_detect_exit(void);
|
void acpi_video_detect_exit(void);
|
||||||
|
|
||||||
|
/*
|
||||||
|
* Indices in the _BCL method response: the first two items are special,
|
||||||
|
* the rest are all supported levels.
|
||||||
|
*
|
||||||
|
* See page 575 of the ACPI spec 3.0
|
||||||
|
*/
|
||||||
|
enum acpi_video_level_idx {
|
||||||
|
ACPI_VIDEO_AC_LEVEL, /* level when machine has full power */
|
||||||
|
ACPI_VIDEO_BATTERY_LEVEL, /* level when machine is on batteries */
|
||||||
|
ACPI_VIDEO_FIRST_LEVEL, /* actual supported levels begin here */
|
||||||
|
};
|
||||||
|
|
||||||
static const struct acpi_device_id video_device_ids[] = {
|
static const struct acpi_device_id video_device_ids[] = {
|
||||||
{ACPI_VIDEO_HID, 0},
|
{ACPI_VIDEO_HID, 0},
|
||||||
{"", 0},
|
{"", 0},
|
||||||
|
@ -132,7 +148,15 @@ struct acpi_video_device_attrib {
|
||||||
the VGA device. */
|
the VGA device. */
|
||||||
u32 pipe_id:3; /* For VGA multiple-head devices. */
|
u32 pipe_id:3; /* For VGA multiple-head devices. */
|
||||||
u32 reserved:10; /* Must be 0 */
|
u32 reserved:10; /* Must be 0 */
|
||||||
u32 device_id_scheme:1; /* Device ID Scheme */
|
|
||||||
|
/*
|
||||||
|
* The device ID might not actually follow the scheme described by this
|
||||||
|
* struct acpi_video_device_attrib. If it does, then this bit
|
||||||
|
* device_id_scheme is set; otherwise, other fields should be ignored.
|
||||||
|
*
|
||||||
|
* (but also see the global flag device_id_scheme)
|
||||||
|
*/
|
||||||
|
u32 device_id_scheme:1;
|
||||||
};
|
};
|
||||||
|
|
||||||
struct acpi_video_enumerated_device {
|
struct acpi_video_enumerated_device {
|
||||||
|
@ -217,20 +241,16 @@ static int acpi_video_get_brightness(struct backlight_device *bd)
|
||||||
|
|
||||||
if (acpi_video_device_lcd_get_level_current(vd, &cur_level, false))
|
if (acpi_video_device_lcd_get_level_current(vd, &cur_level, false))
|
||||||
return -EINVAL;
|
return -EINVAL;
|
||||||
for (i = 2; i < vd->brightness->count; i++) {
|
for (i = ACPI_VIDEO_FIRST_LEVEL; i < vd->brightness->count; i++) {
|
||||||
if (vd->brightness->levels[i] == cur_level)
|
if (vd->brightness->levels[i] == cur_level)
|
||||||
/*
|
return i - ACPI_VIDEO_FIRST_LEVEL;
|
||||||
* The first two entries are special - see page 575
|
|
||||||
* of the ACPI spec 3.0
|
|
||||||
*/
|
|
||||||
return i - 2;
|
|
||||||
}
|
}
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
static int acpi_video_set_brightness(struct backlight_device *bd)
|
static int acpi_video_set_brightness(struct backlight_device *bd)
|
||||||
{
|
{
|
||||||
int request_level = bd->props.brightness + 2;
|
int request_level = bd->props.brightness + ACPI_VIDEO_FIRST_LEVEL;
|
||||||
struct acpi_video_device *vd = bl_get_data(bd);
|
struct acpi_video_device *vd = bl_get_data(bd);
|
||||||
|
|
||||||
cancel_delayed_work(&vd->switch_brightness_work);
|
cancel_delayed_work(&vd->switch_brightness_work);
|
||||||
|
@ -244,18 +264,18 @@ static const struct backlight_ops acpi_backlight_ops = {
|
||||||
};
|
};
|
||||||
|
|
||||||
/* thermal cooling device callbacks */
|
/* thermal cooling device callbacks */
|
||||||
static int video_get_max_state(struct thermal_cooling_device *cooling_dev, unsigned
|
static int video_get_max_state(struct thermal_cooling_device *cooling_dev,
|
||||||
long *state)
|
unsigned long *state)
|
||||||
{
|
{
|
||||||
struct acpi_device *device = cooling_dev->devdata;
|
struct acpi_device *device = cooling_dev->devdata;
|
||||||
struct acpi_video_device *video = acpi_driver_data(device);
|
struct acpi_video_device *video = acpi_driver_data(device);
|
||||||
|
|
||||||
*state = video->brightness->count - 3;
|
*state = video->brightness->count - ACPI_VIDEO_FIRST_LEVEL - 1;
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
static int video_get_cur_state(struct thermal_cooling_device *cooling_dev, unsigned
|
static int video_get_cur_state(struct thermal_cooling_device *cooling_dev,
|
||||||
long *state)
|
unsigned long *state)
|
||||||
{
|
{
|
||||||
struct acpi_device *device = cooling_dev->devdata;
|
struct acpi_device *device = cooling_dev->devdata;
|
||||||
struct acpi_video_device *video = acpi_driver_data(device);
|
struct acpi_video_device *video = acpi_driver_data(device);
|
||||||
|
@ -264,7 +284,8 @@ static int video_get_cur_state(struct thermal_cooling_device *cooling_dev, unsig
|
||||||
|
|
||||||
if (acpi_video_device_lcd_get_level_current(video, &level, false))
|
if (acpi_video_device_lcd_get_level_current(video, &level, false))
|
||||||
return -EINVAL;
|
return -EINVAL;
|
||||||
for (offset = 2; offset < video->brightness->count; offset++)
|
for (offset = ACPI_VIDEO_FIRST_LEVEL; offset < video->brightness->count;
|
||||||
|
offset++)
|
||||||
if (level == video->brightness->levels[offset]) {
|
if (level == video->brightness->levels[offset]) {
|
||||||
*state = video->brightness->count - offset - 1;
|
*state = video->brightness->count - offset - 1;
|
||||||
return 0;
|
return 0;
|
||||||
|
@ -280,7 +301,7 @@ video_set_cur_state(struct thermal_cooling_device *cooling_dev, unsigned long st
|
||||||
struct acpi_video_device *video = acpi_driver_data(device);
|
struct acpi_video_device *video = acpi_driver_data(device);
|
||||||
int level;
|
int level;
|
||||||
|
|
||||||
if (state >= video->brightness->count - 2)
|
if (state >= video->brightness->count - ACPI_VIDEO_FIRST_LEVEL)
|
||||||
return -EINVAL;
|
return -EINVAL;
|
||||||
|
|
||||||
state = video->brightness->count - state;
|
state = video->brightness->count - state;
|
||||||
|
@ -345,10 +366,12 @@ acpi_video_device_lcd_set_level(struct acpi_video_device *device, int level)
|
||||||
}
|
}
|
||||||
|
|
||||||
device->brightness->curr = level;
|
device->brightness->curr = level;
|
||||||
for (state = 2; state < device->brightness->count; state++)
|
for (state = ACPI_VIDEO_FIRST_LEVEL; state < device->brightness->count;
|
||||||
|
state++)
|
||||||
if (level == device->brightness->levels[state]) {
|
if (level == device->brightness->levels[state]) {
|
||||||
if (device->backlight)
|
if (device->backlight)
|
||||||
device->backlight->props.brightness = state - 2;
|
device->backlight->props.brightness =
|
||||||
|
state - ACPI_VIDEO_FIRST_LEVEL;
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -530,14 +553,16 @@ acpi_video_bqc_value_to_level(struct acpi_video_device *device,
|
||||||
|
|
||||||
if (device->brightness->flags._BQC_use_index) {
|
if (device->brightness->flags._BQC_use_index) {
|
||||||
/*
|
/*
|
||||||
* _BQC returns an index that doesn't account for
|
* _BQC returns an index that doesn't account for the first 2
|
||||||
* the first 2 items with special meaning, so we need
|
* items with special meaning (see enum acpi_video_level_idx),
|
||||||
* to compensate for that by offsetting ourselves
|
* so we need to compensate for that by offsetting ourselves
|
||||||
*/
|
*/
|
||||||
if (device->brightness->flags._BCL_reversed)
|
if (device->brightness->flags._BCL_reversed)
|
||||||
bqc_value = device->brightness->count - 3 - bqc_value;
|
bqc_value = device->brightness->count -
|
||||||
|
ACPI_VIDEO_FIRST_LEVEL - 1 - bqc_value;
|
||||||
|
|
||||||
level = device->brightness->levels[bqc_value + 2];
|
level = device->brightness->levels[bqc_value +
|
||||||
|
ACPI_VIDEO_FIRST_LEVEL];
|
||||||
} else {
|
} else {
|
||||||
level = bqc_value;
|
level = bqc_value;
|
||||||
}
|
}
|
||||||
|
@ -571,7 +596,8 @@ acpi_video_device_lcd_get_level_current(struct acpi_video_device *device,
|
||||||
|
|
||||||
*level = acpi_video_bqc_value_to_level(device, *level);
|
*level = acpi_video_bqc_value_to_level(device, *level);
|
||||||
|
|
||||||
for (i = 2; i < device->brightness->count; i++)
|
for (i = ACPI_VIDEO_FIRST_LEVEL;
|
||||||
|
i < device->brightness->count; i++)
|
||||||
if (device->brightness->levels[i] == *level) {
|
if (device->brightness->levels[i] == *level) {
|
||||||
device->brightness->curr = *level;
|
device->brightness->curr = *level;
|
||||||
return 0;
|
return 0;
|
||||||
|
@ -714,9 +740,37 @@ static int acpi_video_bqc_quirk(struct acpi_video_device *device,
|
||||||
|
|
||||||
/*
|
/*
|
||||||
* Some systems always report current brightness level as maximum
|
* Some systems always report current brightness level as maximum
|
||||||
* through _BQC, we need to test another value for them.
|
* through _BQC, we need to test another value for them. However,
|
||||||
|
* there is a subtlety:
|
||||||
|
*
|
||||||
|
* If the _BCL package ordering is descending, the first level
|
||||||
|
* (br->levels[2]) is likely to be 0, and if the number of levels
|
||||||
|
* matches the number of steps, we might confuse a returned level to
|
||||||
|
* mean the index.
|
||||||
|
*
|
||||||
|
* For example:
|
||||||
|
*
|
||||||
|
* current_level = max_level = 100
|
||||||
|
* test_level = 0
|
||||||
|
* returned level = 100
|
||||||
|
*
|
||||||
|
* In this case 100 means the level, not the index, and _BCM failed.
|
||||||
|
* Still, if the _BCL package ordering is descending, the index of
|
||||||
|
* level 0 is also 100, so we assume _BQC is indexed, when it's not.
|
||||||
|
*
|
||||||
|
* This causes all _BQC calls to return bogus values causing weird
|
||||||
|
* behavior from the user's perspective. For example:
|
||||||
|
*
|
||||||
|
* xbacklight -set 10; xbacklight -set 20;
|
||||||
|
*
|
||||||
|
* would flash to 90% and then slowly down to the desired level (20).
|
||||||
|
*
|
||||||
|
* The solution is simple; test anything other than the first level
|
||||||
|
* (e.g. 1).
|
||||||
*/
|
*/
|
||||||
test_level = current_level == max_level ? br->levels[3] : max_level;
|
test_level = current_level == max_level
|
||||||
|
? br->levels[ACPI_VIDEO_FIRST_LEVEL + 1]
|
||||||
|
: max_level;
|
||||||
|
|
||||||
result = acpi_video_device_lcd_set_level(device, test_level);
|
result = acpi_video_device_lcd_set_level(device, test_level);
|
||||||
if (result)
|
if (result)
|
||||||
|
@ -730,8 +784,8 @@ static int acpi_video_bqc_quirk(struct acpi_video_device *device,
|
||||||
/* buggy _BQC found, need to find out if it uses index */
|
/* buggy _BQC found, need to find out if it uses index */
|
||||||
if (level < br->count) {
|
if (level < br->count) {
|
||||||
if (br->flags._BCL_reversed)
|
if (br->flags._BCL_reversed)
|
||||||
level = br->count - 3 - level;
|
level = br->count - ACPI_VIDEO_FIRST_LEVEL - 1 - level;
|
||||||
if (br->levels[level + 2] == test_level)
|
if (br->levels[level + ACPI_VIDEO_FIRST_LEVEL] == test_level)
|
||||||
br->flags._BQC_use_index = 1;
|
br->flags._BQC_use_index = 1;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -761,7 +815,7 @@ int acpi_video_get_levels(struct acpi_device *device,
|
||||||
goto out;
|
goto out;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (obj->package.count < 2) {
|
if (obj->package.count < ACPI_VIDEO_FIRST_LEVEL) {
|
||||||
result = -EINVAL;
|
result = -EINVAL;
|
||||||
goto out;
|
goto out;
|
||||||
}
|
}
|
||||||
|
@ -773,8 +827,13 @@ int acpi_video_get_levels(struct acpi_device *device,
|
||||||
goto out;
|
goto out;
|
||||||
}
|
}
|
||||||
|
|
||||||
br->levels = kmalloc((obj->package.count + 2) * sizeof *(br->levels),
|
/*
|
||||||
GFP_KERNEL);
|
* Note that we have to reserve 2 extra items (ACPI_VIDEO_FIRST_LEVEL),
|
||||||
|
* in order to account for buggy BIOS which don't export the first two
|
||||||
|
* special levels (see below)
|
||||||
|
*/
|
||||||
|
br->levels = kmalloc((obj->package.count + ACPI_VIDEO_FIRST_LEVEL) *
|
||||||
|
sizeof(*br->levels), GFP_KERNEL);
|
||||||
if (!br->levels) {
|
if (!br->levels) {
|
||||||
result = -ENOMEM;
|
result = -ENOMEM;
|
||||||
goto out_free;
|
goto out_free;
|
||||||
|
@ -788,7 +847,8 @@ int acpi_video_get_levels(struct acpi_device *device,
|
||||||
}
|
}
|
||||||
value = (u32) o->integer.value;
|
value = (u32) o->integer.value;
|
||||||
/* Skip duplicate entries */
|
/* Skip duplicate entries */
|
||||||
if (count > 2 && br->levels[count - 1] == value)
|
if (count > ACPI_VIDEO_FIRST_LEVEL
|
||||||
|
&& br->levels[count - 1] == value)
|
||||||
continue;
|
continue;
|
||||||
|
|
||||||
br->levels[count] = value;
|
br->levels[count] = value;
|
||||||
|
@ -804,26 +864,29 @@ int acpi_video_get_levels(struct acpi_device *device,
|
||||||
* In this case, the first two elements in _BCL packages
|
* In this case, the first two elements in _BCL packages
|
||||||
* are also supported brightness levels that OS should take care of.
|
* are also supported brightness levels that OS should take care of.
|
||||||
*/
|
*/
|
||||||
for (i = 2; i < count; i++) {
|
for (i = ACPI_VIDEO_FIRST_LEVEL; i < count; i++) {
|
||||||
if (br->levels[i] == br->levels[0])
|
if (br->levels[i] == br->levels[ACPI_VIDEO_AC_LEVEL])
|
||||||
level_ac_battery++;
|
level_ac_battery++;
|
||||||
if (br->levels[i] == br->levels[1])
|
if (br->levels[i] == br->levels[ACPI_VIDEO_BATTERY_LEVEL])
|
||||||
level_ac_battery++;
|
level_ac_battery++;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (level_ac_battery < 2) {
|
if (level_ac_battery < ACPI_VIDEO_FIRST_LEVEL) {
|
||||||
level_ac_battery = 2 - level_ac_battery;
|
level_ac_battery = ACPI_VIDEO_FIRST_LEVEL - level_ac_battery;
|
||||||
br->flags._BCL_no_ac_battery_levels = 1;
|
br->flags._BCL_no_ac_battery_levels = 1;
|
||||||
for (i = (count - 1 + level_ac_battery); i >= 2; i--)
|
for (i = (count - 1 + level_ac_battery);
|
||||||
|
i >= ACPI_VIDEO_FIRST_LEVEL; i--)
|
||||||
br->levels[i] = br->levels[i - level_ac_battery];
|
br->levels[i] = br->levels[i - level_ac_battery];
|
||||||
count += level_ac_battery;
|
count += level_ac_battery;
|
||||||
} else if (level_ac_battery > 2)
|
} else if (level_ac_battery > ACPI_VIDEO_FIRST_LEVEL)
|
||||||
ACPI_ERROR((AE_INFO, "Too many duplicates in _BCL package"));
|
ACPI_ERROR((AE_INFO, "Too many duplicates in _BCL package"));
|
||||||
|
|
||||||
/* Check if the _BCL package is in a reversed order */
|
/* Check if the _BCL package is in a reversed order */
|
||||||
if (max_level == br->levels[2]) {
|
if (max_level == br->levels[ACPI_VIDEO_FIRST_LEVEL]) {
|
||||||
br->flags._BCL_reversed = 1;
|
br->flags._BCL_reversed = 1;
|
||||||
sort(&br->levels[2], count - 2, sizeof(br->levels[2]),
|
sort(&br->levels[ACPI_VIDEO_FIRST_LEVEL],
|
||||||
|
count - ACPI_VIDEO_FIRST_LEVEL,
|
||||||
|
sizeof(br->levels[ACPI_VIDEO_FIRST_LEVEL]),
|
||||||
acpi_video_cmp_level, NULL);
|
acpi_video_cmp_level, NULL);
|
||||||
} else if (max_level != br->levels[count - 1])
|
} else if (max_level != br->levels[count - 1])
|
||||||
ACPI_ERROR((AE_INFO,
|
ACPI_ERROR((AE_INFO,
|
||||||
|
@ -894,7 +957,7 @@ acpi_video_init_brightness(struct acpi_video_device *device)
|
||||||
* level_old is invalid (no matter whether it's a level
|
* level_old is invalid (no matter whether it's a level
|
||||||
* or an index). Set the backlight to max_level in this case.
|
* or an index). Set the backlight to max_level in this case.
|
||||||
*/
|
*/
|
||||||
for (i = 2; i < br->count; i++)
|
for (i = ACPI_VIDEO_FIRST_LEVEL; i < br->count; i++)
|
||||||
if (level == br->levels[i])
|
if (level == br->levels[i])
|
||||||
break;
|
break;
|
||||||
if (i == br->count || !level)
|
if (i == br->count || !level)
|
||||||
|
@ -906,7 +969,8 @@ acpi_video_init_brightness(struct acpi_video_device *device)
|
||||||
goto out_free_levels;
|
goto out_free_levels;
|
||||||
|
|
||||||
ACPI_DEBUG_PRINT((ACPI_DB_INFO,
|
ACPI_DEBUG_PRINT((ACPI_DB_INFO,
|
||||||
"found %d brightness levels\n", br->count - 2));
|
"found %d brightness levels\n",
|
||||||
|
br->count - ACPI_VIDEO_FIRST_LEVEL));
|
||||||
return 0;
|
return 0;
|
||||||
|
|
||||||
out_free_levels:
|
out_free_levels:
|
||||||
|
@ -1297,7 +1361,7 @@ acpi_video_get_next_level(struct acpi_video_device *device,
|
||||||
max = max_below = 0;
|
max = max_below = 0;
|
||||||
min = min_above = 255;
|
min = min_above = 255;
|
||||||
/* Find closest level to level_current */
|
/* Find closest level to level_current */
|
||||||
for (i = 2; i < device->brightness->count; i++) {
|
for (i = ACPI_VIDEO_FIRST_LEVEL; i < device->brightness->count; i++) {
|
||||||
l = device->brightness->levels[i];
|
l = device->brightness->levels[i];
|
||||||
if (abs(l - level_current) < abs(delta)) {
|
if (abs(l - level_current) < abs(delta)) {
|
||||||
delta = l - level_current;
|
delta = l - level_current;
|
||||||
|
@ -1307,7 +1371,7 @@ acpi_video_get_next_level(struct acpi_video_device *device,
|
||||||
}
|
}
|
||||||
/* Ajust level_current to closest available level */
|
/* Ajust level_current to closest available level */
|
||||||
level_current += delta;
|
level_current += delta;
|
||||||
for (i = 2; i < device->brightness->count; i++) {
|
for (i = ACPI_VIDEO_FIRST_LEVEL; i < device->brightness->count; i++) {
|
||||||
l = device->brightness->levels[i];
|
l = device->brightness->levels[i];
|
||||||
if (l < min)
|
if (l < min)
|
||||||
min = l;
|
min = l;
|
||||||
|
@ -1680,7 +1744,8 @@ static void acpi_video_dev_register_backlight(struct acpi_video_device *device)
|
||||||
|
|
||||||
memset(&props, 0, sizeof(struct backlight_properties));
|
memset(&props, 0, sizeof(struct backlight_properties));
|
||||||
props.type = BACKLIGHT_FIRMWARE;
|
props.type = BACKLIGHT_FIRMWARE;
|
||||||
props.max_brightness = device->brightness->count - 3;
|
props.max_brightness =
|
||||||
|
device->brightness->count - ACPI_VIDEO_FIRST_LEVEL - 1;
|
||||||
device->backlight = backlight_device_register(name,
|
device->backlight = backlight_device_register(name,
|
||||||
parent,
|
parent,
|
||||||
device,
|
device,
|
||||||
|
|
|
@ -67,6 +67,7 @@ MODULE_DESCRIPTION("ACPI Battery Driver");
|
||||||
MODULE_LICENSE("GPL");
|
MODULE_LICENSE("GPL");
|
||||||
|
|
||||||
static async_cookie_t async_cookie;
|
static async_cookie_t async_cookie;
|
||||||
|
static bool battery_driver_registered;
|
||||||
static int battery_bix_broken_package;
|
static int battery_bix_broken_package;
|
||||||
static int battery_notification_delay_ms;
|
static int battery_notification_delay_ms;
|
||||||
static unsigned int cache_time = 1000;
|
static unsigned int cache_time = 1000;
|
||||||
|
@ -93,6 +94,11 @@ static const struct acpi_device_id battery_device_ids[] = {
|
||||||
|
|
||||||
MODULE_DEVICE_TABLE(acpi, battery_device_ids);
|
MODULE_DEVICE_TABLE(acpi, battery_device_ids);
|
||||||
|
|
||||||
|
/* Lists of PMIC ACPI HIDs with an (often better) native battery driver */
|
||||||
|
static const char * const acpi_battery_blacklist[] = {
|
||||||
|
"INT33F4", /* X-Powers AXP288 PMIC */
|
||||||
|
};
|
||||||
|
|
||||||
enum {
|
enum {
|
||||||
ACPI_BATTERY_ALARM_PRESENT,
|
ACPI_BATTERY_ALARM_PRESENT,
|
||||||
ACPI_BATTERY_XINFO_PRESENT,
|
ACPI_BATTERY_XINFO_PRESENT,
|
||||||
|
@ -1315,8 +1321,17 @@ static struct acpi_driver acpi_battery_driver = {
|
||||||
|
|
||||||
static void __init acpi_battery_init_async(void *unused, async_cookie_t cookie)
|
static void __init acpi_battery_init_async(void *unused, async_cookie_t cookie)
|
||||||
{
|
{
|
||||||
|
unsigned int i;
|
||||||
int result;
|
int result;
|
||||||
|
|
||||||
|
for (i = 0; i < ARRAY_SIZE(acpi_battery_blacklist); i++)
|
||||||
|
if (acpi_dev_present(acpi_battery_blacklist[i], "1", -1)) {
|
||||||
|
pr_info(PREFIX ACPI_BATTERY_DEVICE_NAME
|
||||||
|
": found native %s PMIC, not loading\n",
|
||||||
|
acpi_battery_blacklist[i]);
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
dmi_check_system(bat_dmi_table);
|
dmi_check_system(bat_dmi_table);
|
||||||
|
|
||||||
#ifdef CONFIG_ACPI_PROCFS_POWER
|
#ifdef CONFIG_ACPI_PROCFS_POWER
|
||||||
|
@ -1329,6 +1344,7 @@ static void __init acpi_battery_init_async(void *unused, async_cookie_t cookie)
|
||||||
if (result < 0)
|
if (result < 0)
|
||||||
acpi_unlock_battery_dir(acpi_battery_dir);
|
acpi_unlock_battery_dir(acpi_battery_dir);
|
||||||
#endif
|
#endif
|
||||||
|
battery_driver_registered = (result == 0);
|
||||||
}
|
}
|
||||||
|
|
||||||
static int __init acpi_battery_init(void)
|
static int __init acpi_battery_init(void)
|
||||||
|
@ -1343,8 +1359,10 @@ static int __init acpi_battery_init(void)
|
||||||
static void __exit acpi_battery_exit(void)
|
static void __exit acpi_battery_exit(void)
|
||||||
{
|
{
|
||||||
async_synchronize_cookie(async_cookie + 1);
|
async_synchronize_cookie(async_cookie + 1);
|
||||||
|
if (battery_driver_registered)
|
||||||
acpi_bus_unregister_driver(&acpi_battery_driver);
|
acpi_bus_unregister_driver(&acpi_battery_driver);
|
||||||
#ifdef CONFIG_ACPI_PROCFS_POWER
|
#ifdef CONFIG_ACPI_PROCFS_POWER
|
||||||
|
if (acpi_battery_dir)
|
||||||
acpi_unlock_battery_dir(acpi_battery_dir);
|
acpi_unlock_battery_dir(acpi_battery_dir);
|
||||||
#endif
|
#endif
|
||||||
}
|
}
|
||||||
|
|
|
@ -188,6 +188,14 @@ static struct dmi_system_id acpi_rev_dmi_table[] __initdata = {
|
||||||
DMI_MATCH(DMI_PRODUCT_NAME, "Latitude 3350"),
|
DMI_MATCH(DMI_PRODUCT_NAME, "Latitude 3350"),
|
||||||
},
|
},
|
||||||
},
|
},
|
||||||
|
{
|
||||||
|
.callback = dmi_enable_rev_override,
|
||||||
|
.ident = "DELL Inspiron 7537",
|
||||||
|
.matches = {
|
||||||
|
DMI_MATCH(DMI_SYS_VENDOR, "Dell Inc."),
|
||||||
|
DMI_MATCH(DMI_PRODUCT_NAME, "Inspiron 7537"),
|
||||||
|
},
|
||||||
|
},
|
||||||
#endif
|
#endif
|
||||||
{}
|
{}
|
||||||
};
|
};
|
||||||
|
|
|
@ -736,6 +736,72 @@ bool acpi_dev_found(const char *hid)
|
||||||
}
|
}
|
||||||
EXPORT_SYMBOL(acpi_dev_found);
|
EXPORT_SYMBOL(acpi_dev_found);
|
||||||
|
|
||||||
|
struct acpi_dev_present_info {
|
||||||
|
struct acpi_device_id hid[2];
|
||||||
|
const char *uid;
|
||||||
|
s64 hrv;
|
||||||
|
};
|
||||||
|
|
||||||
|
static int acpi_dev_present_cb(struct device *dev, void *data)
|
||||||
|
{
|
||||||
|
struct acpi_device *adev = to_acpi_device(dev);
|
||||||
|
struct acpi_dev_present_info *match = data;
|
||||||
|
unsigned long long hrv;
|
||||||
|
acpi_status status;
|
||||||
|
|
||||||
|
if (acpi_match_device_ids(adev, match->hid))
|
||||||
|
return 0;
|
||||||
|
|
||||||
|
if (match->uid && (!adev->pnp.unique_id ||
|
||||||
|
strcmp(adev->pnp.unique_id, match->uid)))
|
||||||
|
return 0;
|
||||||
|
|
||||||
|
if (match->hrv == -1)
|
||||||
|
return 1;
|
||||||
|
|
||||||
|
status = acpi_evaluate_integer(adev->handle, "_HRV", NULL, &hrv);
|
||||||
|
if (ACPI_FAILURE(status))
|
||||||
|
return 0;
|
||||||
|
|
||||||
|
return hrv == match->hrv;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* acpi_dev_present - Detect that a given ACPI device is present
|
||||||
|
* @hid: Hardware ID of the device.
|
||||||
|
* @uid: Unique ID of the device, pass NULL to not check _UID
|
||||||
|
* @hrv: Hardware Revision of the device, pass -1 to not check _HRV
|
||||||
|
*
|
||||||
|
* Return %true if a matching device was present at the moment of invocation.
|
||||||
|
* Note that if the device is pluggable, it may since have disappeared.
|
||||||
|
*
|
||||||
|
* Note that unlike acpi_dev_found() this function checks the status
|
||||||
|
* of the device. So for devices which are present in the dsdt, but
|
||||||
|
* which are disabled (their _STA callback returns 0) this function
|
||||||
|
* will return false.
|
||||||
|
*
|
||||||
|
* For this function to work, acpi_bus_scan() must have been executed
|
||||||
|
* which happens in the subsys_initcall() subsection. Hence, do not
|
||||||
|
* call from a subsys_initcall() or earlier (use acpi_get_devices()
|
||||||
|
* instead). Calling from module_init() is fine (which is synonymous
|
||||||
|
* with device_initcall()).
|
||||||
|
*/
|
||||||
|
bool acpi_dev_present(const char *hid, const char *uid, s64 hrv)
|
||||||
|
{
|
||||||
|
struct acpi_dev_present_info match = {};
|
||||||
|
struct device *dev;
|
||||||
|
|
||||||
|
strlcpy(match.hid[0].id, hid, sizeof(match.hid[0].id));
|
||||||
|
match.uid = uid;
|
||||||
|
match.hrv = hrv;
|
||||||
|
|
||||||
|
dev = bus_find_device(&acpi_bus_type, NULL, &match,
|
||||||
|
acpi_dev_present_cb);
|
||||||
|
|
||||||
|
return !!dev;
|
||||||
|
}
|
||||||
|
EXPORT_SYMBOL(acpi_dev_present);
|
||||||
|
|
||||||
/*
|
/*
|
||||||
* acpi_backlight= handling, this is done here rather then in video_detect.c
|
* acpi_backlight= handling, this is done here rather then in video_detect.c
|
||||||
* because __setup cannot be used in modules.
|
* because __setup cannot be used in modules.
|
||||||
|
|
|
@ -14,6 +14,7 @@
|
||||||
* GNU General Public License for more details.
|
* GNU General Public License for more details.
|
||||||
*/
|
*/
|
||||||
|
|
||||||
|
#include <linux/acpi.h>
|
||||||
#include <linux/module.h>
|
#include <linux/module.h>
|
||||||
#include <linux/device.h>
|
#include <linux/device.h>
|
||||||
#include <linux/regmap.h>
|
#include <linux/regmap.h>
|
||||||
|
@ -113,7 +114,8 @@
|
||||||
#define ILIM_3000MA 3000 /* 3000mA */
|
#define ILIM_3000MA 3000 /* 3000mA */
|
||||||
|
|
||||||
#define AXP288_EXTCON_DEV_NAME "axp288_extcon"
|
#define AXP288_EXTCON_DEV_NAME "axp288_extcon"
|
||||||
#define USB_HOST_EXTCON_DEV_NAME "INT3496:00"
|
#define USB_HOST_EXTCON_HID "INT3496"
|
||||||
|
#define USB_HOST_EXTCON_NAME "INT3496:00"
|
||||||
|
|
||||||
static const unsigned int cable_ids[] =
|
static const unsigned int cable_ids[] =
|
||||||
{ EXTCON_CHG_USB_SDP, EXTCON_CHG_USB_CDP, EXTCON_CHG_USB_DCP };
|
{ EXTCON_CHG_USB_SDP, EXTCON_CHG_USB_CDP, EXTCON_CHG_USB_DCP };
|
||||||
|
@ -807,11 +809,15 @@ static int axp288_charger_probe(struct platform_device *pdev)
|
||||||
return -EPROBE_DEFER;
|
return -EPROBE_DEFER;
|
||||||
}
|
}
|
||||||
|
|
||||||
info->otg.cable = extcon_get_extcon_dev(USB_HOST_EXTCON_DEV_NAME);
|
if (acpi_dev_present(USB_HOST_EXTCON_HID, NULL, -1)) {
|
||||||
|
info->otg.cable = extcon_get_extcon_dev(USB_HOST_EXTCON_NAME);
|
||||||
if (info->otg.cable == NULL) {
|
if (info->otg.cable == NULL) {
|
||||||
dev_dbg(dev, "EXTCON_USB_HOST is not ready, probe deferred\n");
|
dev_dbg(dev, "EXTCON_USB_HOST is not ready, probe deferred\n");
|
||||||
return -EPROBE_DEFER;
|
return -EPROBE_DEFER;
|
||||||
}
|
}
|
||||||
|
dev_info(&pdev->dev,
|
||||||
|
"Using " USB_HOST_EXTCON_HID " extcon for usb-id\n");
|
||||||
|
}
|
||||||
|
|
||||||
platform_set_drvdata(pdev, info);
|
platform_set_drvdata(pdev, info);
|
||||||
mutex_init(&info->lock);
|
mutex_init(&info->lock);
|
||||||
|
@ -849,6 +855,7 @@ static int axp288_charger_probe(struct platform_device *pdev)
|
||||||
/* Register for OTG notification */
|
/* Register for OTG notification */
|
||||||
INIT_WORK(&info->otg.work, axp288_charger_otg_evt_worker);
|
INIT_WORK(&info->otg.work, axp288_charger_otg_evt_worker);
|
||||||
info->otg.id_nb.notifier_call = axp288_charger_handle_otg_evt;
|
info->otg.id_nb.notifier_call = axp288_charger_handle_otg_evt;
|
||||||
|
if (info->otg.cable) {
|
||||||
ret = devm_extcon_register_notifier(&pdev->dev, info->otg.cable,
|
ret = devm_extcon_register_notifier(&pdev->dev, info->otg.cable,
|
||||||
EXTCON_USB_HOST, &info->otg.id_nb);
|
EXTCON_USB_HOST, &info->otg.id_nb);
|
||||||
if (ret) {
|
if (ret) {
|
||||||
|
@ -856,6 +863,7 @@ static int axp288_charger_probe(struct platform_device *pdev)
|
||||||
return ret;
|
return ret;
|
||||||
}
|
}
|
||||||
schedule_work(&info->otg.work);
|
schedule_work(&info->otg.work);
|
||||||
|
}
|
||||||
|
|
||||||
/* Register charger interrupts */
|
/* Register charger interrupts */
|
||||||
for (i = 0; i < CHRG_INTR_END; i++) {
|
for (i = 0; i < CHRG_INTR_END; i++) {
|
||||||
|
|
|
@ -88,6 +88,7 @@ acpi_evaluate_dsm_typed(acpi_handle handle, const u8 *uuid, u64 rev, u64 func,
|
||||||
}
|
}
|
||||||
|
|
||||||
bool acpi_dev_found(const char *hid);
|
bool acpi_dev_found(const char *hid);
|
||||||
|
bool acpi_dev_present(const char *hid, const char *uid, s64 hrv);
|
||||||
|
|
||||||
#ifdef CONFIG_ACPI
|
#ifdef CONFIG_ACPI
|
||||||
|
|
||||||
|
|
|
@ -607,6 +607,11 @@ static inline bool acpi_dev_found(const char *hid)
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
static inline bool acpi_dev_present(const char *hid, const char *uid, s64 hrv)
|
||||||
|
{
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
static inline bool is_acpi_node(struct fwnode_handle *fwnode)
|
static inline bool is_acpi_node(struct fwnode_handle *fwnode)
|
||||||
{
|
{
|
||||||
return false;
|
return false;
|
||||||
|
|
Loading…
Add table
Reference in a new issue