|
|
e336be |
From 9e2ef73d9d72ab312bef34ba318fdcb77facb1f0 Mon Sep 17 00:00:00 2001
|
|
|
e336be |
From: Hans de Goede <hdegoede@redhat.com>
|
|
|
e336be |
Date: Mon, 27 Aug 2018 09:47:42 +0200
|
|
|
e336be |
Subject: [PATCH 1/7] pwm: lpss: Add ACPI HID for second PWM controller on
|
|
|
e336be |
Cherry Trail devices
|
|
|
e336be |
|
|
|
e336be |
The second PWM controller on Cherry Trail devices uses a separate ACPI
|
|
|
e336be |
HID: "80862289", add this so that the driver will properly bind to the
|
|
|
e336be |
second PWM controller.
|
|
|
e336be |
|
|
|
e336be |
The second PWM controller is usually not used, the main thing gained by
|
|
|
e336be |
this is properly putting the PWM controller in D3 on suspend.
|
|
|
e336be |
|
|
|
e336be |
Reviewed-by: Andy Shevchenko <andriy.shevchenko@linux.intel.com>
|
|
|
e336be |
Signed-off-by: Hans de Goede <hdegoede@redhat.com>
|
|
|
e336be |
---
|
|
|
e336be |
drivers/pwm/pwm-lpss-platform.c | 1 +
|
|
|
e336be |
1 file changed, 1 insertion(+)
|
|
|
e336be |
|
|
|
e336be |
diff --git a/drivers/pwm/pwm-lpss-platform.c b/drivers/pwm/pwm-lpss-platform.c
|
|
|
e336be |
index 5561b9e190f8..7304f36ee715 100644
|
|
|
e336be |
--- a/drivers/pwm/pwm-lpss-platform.c
|
|
|
e336be |
+++ b/drivers/pwm/pwm-lpss-platform.c
|
|
|
e336be |
@@ -81,6 +81,7 @@ static SIMPLE_DEV_PM_OPS(pwm_lpss_platform_pm_ops,
|
|
|
e336be |
static const struct acpi_device_id pwm_lpss_acpi_match[] = {
|
|
|
e336be |
{ "80860F09", (unsigned long)&pwm_lpss_byt_info },
|
|
|
e336be |
{ "80862288", (unsigned long)&pwm_lpss_bsw_info },
|
|
|
e336be |
+ { "80862289", (unsigned long)&pwm_lpss_bsw_info },
|
|
|
e336be |
{ "80865AC8", (unsigned long)&pwm_lpss_bxt_info },
|
|
|
e336be |
{ },
|
|
|
e336be |
};
|
|
|
e336be |
--
|
|
|
e336be |
2.19.1
|
|
|
e336be |
|
|
|
e336be |
From f215ee5bd62ab40ee34c318df1af61991dead98d Mon Sep 17 00:00:00 2001
|
|
|
e336be |
From: Hans de Goede <hdegoede@redhat.com>
|
|
|
e336be |
Date: Tue, 11 Sep 2018 16:07:41 +0200
|
|
|
e336be |
Subject: [PATCH 2/7] pwm: lpss: Move struct pwm_lpss_chip definition to the
|
|
|
e336be |
header file
|
|
|
e336be |
|
|
|
e336be |
Move struct pwm_lpss_chip definition from pwm-lpss.c to pwm-lpss.h,
|
|
|
e336be |
so that the pci/platform drivers can access the info member
|
|
|
e336be |
(struct pwm_lpss_boardinfo *).
|
|
|
e336be |
|
|
|
e336be |
This is a preparation patch for adding platform specific quirks, which
|
|
|
e336be |
the drivers need access to, to pwm_lpss_boardinfo.
|
|
|
e336be |
|
|
|
e336be |
Reviewed-by: Andy Shevchenko <andriy.shevchenko@linux.intel.com>
|
|
|
e336be |
Signed-off-by: Hans de Goede <hdegoede@redhat.com>
|
|
|
e336be |
---
|
|
|
e336be |
Changes in v4:
|
|
|
e336be |
-No changes in v4 of this patch-set
|
|
|
e336be |
|
|
|
e336be |
Changes in v3:
|
|
|
e336be |
-There was no v3, but I accidentally put v3 in the Subject of the v2
|
|
|
e336be |
patches, so lets skip v3
|
|
|
e336be |
|
|
|
e336be |
Changes in v2:
|
|
|
e336be |
-No changes in v2 of this patch-set
|
|
|
e336be |
---
|
|
|
e336be |
drivers/pwm/pwm-lpss.c | 9 ---------
|
|
|
e336be |
drivers/pwm/pwm-lpss.h | 9 ++++++++-
|
|
|
e336be |
2 files changed, 8 insertions(+), 10 deletions(-)
|
|
|
e336be |
|
|
|
e336be |
diff --git a/drivers/pwm/pwm-lpss.c b/drivers/pwm/pwm-lpss.c
|
|
|
e336be |
index 4721a264bac2..e602835fd6de 100644
|
|
|
e336be |
--- a/drivers/pwm/pwm-lpss.c
|
|
|
e336be |
+++ b/drivers/pwm/pwm-lpss.c
|
|
|
e336be |
@@ -32,15 +32,6 @@
|
|
|
e336be |
/* Size of each PWM register space if multiple */
|
|
|
e336be |
#define PWM_SIZE 0x400
|
|
|
e336be |
|
|
|
e336be |
-#define MAX_PWMS 4
|
|
|
e336be |
-
|
|
|
e336be |
-struct pwm_lpss_chip {
|
|
|
e336be |
- struct pwm_chip chip;
|
|
|
e336be |
- void __iomem *regs;
|
|
|
e336be |
- const struct pwm_lpss_boardinfo *info;
|
|
|
e336be |
- u32 saved_ctrl[MAX_PWMS];
|
|
|
e336be |
-};
|
|
|
e336be |
-
|
|
|
e336be |
static inline struct pwm_lpss_chip *to_lpwm(struct pwm_chip *chip)
|
|
|
e336be |
{
|
|
|
e336be |
return container_of(chip, struct pwm_lpss_chip, chip);
|
|
|
e336be |
diff --git a/drivers/pwm/pwm-lpss.h b/drivers/pwm/pwm-lpss.h
|
|
|
e336be |
index 7a4238ad1fcb..8f029ed263af 100644
|
|
|
e336be |
--- a/drivers/pwm/pwm-lpss.h
|
|
|
e336be |
+++ b/drivers/pwm/pwm-lpss.h
|
|
|
e336be |
@@ -16,7 +16,14 @@
|
|
|
e336be |
#include <linux/device.h>
|
|
|
e336be |
#include <linux/pwm.h>
|
|
|
e336be |
|
|
|
e336be |
-struct pwm_lpss_chip;
|
|
|
e336be |
+#define MAX_PWMS 4
|
|
|
e336be |
+
|
|
|
e336be |
+struct pwm_lpss_chip {
|
|
|
e336be |
+ struct pwm_chip chip;
|
|
|
e336be |
+ void __iomem *regs;
|
|
|
e336be |
+ const struct pwm_lpss_boardinfo *info;
|
|
|
e336be |
+ u32 saved_ctrl[MAX_PWMS];
|
|
|
e336be |
+};
|
|
|
e336be |
|
|
|
e336be |
struct pwm_lpss_boardinfo {
|
|
|
e336be |
unsigned long clk_rate;
|
|
|
e336be |
--
|
|
|
e336be |
2.19.1
|
|
|
e336be |
|
|
|
e336be |
From eb73756876f92ad0da4259400bce50881cb332b7 Mon Sep 17 00:00:00 2001
|
|
|
e336be |
From: Hans de Goede <hdegoede@redhat.com>
|
|
|
e336be |
Date: Mon, 10 Sep 2018 15:30:58 +0200
|
|
|
e336be |
Subject: [PATCH 3/7] pwm: lpss: Check PWM powerstate after resume on Cherry
|
|
|
e336be |
Trail devices
|
|
|
e336be |
|
|
|
e336be |
The _PS0 method for the integrated graphics on some Cherry Trail devices
|
|
|
e336be |
(observed on a HP Pavilion X2 10-p0XX) turns on the PWM chip (puts it in
|
|
|
e336be |
D0), causing an inconsistency between the state the pm-core thinks it is
|
|
|
e336be |
in (left runtime suspended as it was before the suspend/resume) and the
|
|
|
e336be |
state it actually is in.
|
|
|
e336be |
|
|
|
e336be |
Interestingly enough this is done on a device where the pwm controller is
|
|
|
e336be |
not used for the backlight at all, since it uses an eDP panel. On devices
|
|
|
e336be |
where the PWM is used this is not a problem since we will resume it
|
|
|
e336be |
ourselves anyways.
|
|
|
e336be |
|
|
|
e336be |
This inconsistency causes us to never suspend the pwm controller again,
|
|
|
e336be |
which causes the device to not be able to reach S0ix states when suspended.
|
|
|
e336be |
|
|
|
e336be |
This commit adds a resume-complete handler, which when we think the device
|
|
|
e336be |
is still run-time suspended checks the actual power-state and if necessary
|
|
|
e336be |
updates the rpm-core's internal state.
|
|
|
e336be |
|
|
|
e336be |
This fixes the Pavilion X2 10-p0XX not reaching S0ix states when suspended.
|
|
|
e336be |
|
|
|
e336be |
Reviewed-by: Andy Shevchenko <andriy.shevchenko@linux.intel.com>
|
|
|
e336be |
Signed-off-by: Hans de Goede <hdegoede@redhat.com>
|
|
|
e336be |
---
|
|
|
e336be |
Changes in v4:
|
|
|
e336be |
-Use acpi_device_get_power() instead of manually calling _PSC
|
|
|
e336be |
|
|
|
e336be |
Changes in v3:
|
|
|
e336be |
-There was no v3, but I accidentally put v3 in the Subject of the v2
|
|
|
e336be |
patches, so lets skip v3
|
|
|
e336be |
|
|
|
e336be |
Changes in v2:
|
|
|
e336be |
-Do the pm_runtime_en/disable before/after checking the power-state
|
|
|
e336be |
---
|
|
|
e336be |
drivers/pwm/pwm-lpss-platform.c | 25 ++++++++++++++++++++++---
|
|
|
e336be |
drivers/pwm/pwm-lpss.h | 2 ++
|
|
|
e336be |
2 files changed, 24 insertions(+), 3 deletions(-)
|
|
|
e336be |
|
|
|
e336be |
diff --git a/drivers/pwm/pwm-lpss-platform.c b/drivers/pwm/pwm-lpss-platform.c
|
|
|
e336be |
index 7304f36ee715..b6edf8af26cc 100644
|
|
|
e336be |
--- a/drivers/pwm/pwm-lpss-platform.c
|
|
|
e336be |
+++ b/drivers/pwm/pwm-lpss-platform.c
|
|
|
e336be |
@@ -30,6 +30,7 @@ static const struct pwm_lpss_boardinfo pwm_lpss_bsw_info = {
|
|
|
e336be |
.clk_rate = 19200000,
|
|
|
e336be |
.npwm = 1,
|
|
|
e336be |
.base_unit_bits = 16,
|
|
|
e336be |
+ .check_power_on_resume = true,
|
|
|
e336be |
};
|
|
|
e336be |
|
|
|
e336be |
/* Broxton */
|
|
|
e336be |
@@ -74,9 +75,27 @@ static int pwm_lpss_remove_platform(struct platform_device *pdev)
|
|
|
e336be |
return pwm_lpss_remove(lpwm);
|
|
|
e336be |
}
|
|
|
e336be |
|
|
|
e336be |
-static SIMPLE_DEV_PM_OPS(pwm_lpss_platform_pm_ops,
|
|
|
e336be |
- pwm_lpss_suspend,
|
|
|
e336be |
- pwm_lpss_resume);
|
|
|
e336be |
+static void pwm_lpss_complete(struct device *dev)
|
|
|
e336be |
+{
|
|
|
e336be |
+ struct pwm_lpss_chip *lpwm = dev_get_drvdata(dev);
|
|
|
e336be |
+ int ret, state;
|
|
|
e336be |
+
|
|
|
e336be |
+ /* The PWM may be turned on by AML code, update our state to match */
|
|
|
e336be |
+ if (pm_runtime_suspended(dev) && lpwm->info->check_power_on_resume) {
|
|
|
e336be |
+ pm_runtime_disable(dev);
|
|
|
e336be |
+
|
|
|
e336be |
+ ret = acpi_device_get_power(ACPI_COMPANION(dev), &state);
|
|
|
e336be |
+ if (ret == 0 && state == ACPI_STATE_D0)
|
|
|
e336be |
+ pm_runtime_set_active(dev);
|
|
|
e336be |
+
|
|
|
e336be |
+ pm_runtime_enable(dev);
|
|
|
e336be |
+ }
|
|
|
e336be |
+}
|
|
|
e336be |
+
|
|
|
e336be |
+static const struct dev_pm_ops pwm_lpss_platform_pm_ops = {
|
|
|
e336be |
+ .complete = pwm_lpss_complete,
|
|
|
e336be |
+ SET_SYSTEM_SLEEP_PM_OPS(pwm_lpss_suspend, pwm_lpss_resume)
|
|
|
e336be |
+};
|
|
|
e336be |
|
|
|
e336be |
static const struct acpi_device_id pwm_lpss_acpi_match[] = {
|
|
|
e336be |
{ "80860F09", (unsigned long)&pwm_lpss_byt_info },
|
|
|
e336be |
diff --git a/drivers/pwm/pwm-lpss.h b/drivers/pwm/pwm-lpss.h
|
|
|
e336be |
index 8f029ed263af..1a2575d25bea 100644
|
|
|
e336be |
--- a/drivers/pwm/pwm-lpss.h
|
|
|
e336be |
+++ b/drivers/pwm/pwm-lpss.h
|
|
|
e336be |
@@ -30,6 +30,8 @@ struct pwm_lpss_boardinfo {
|
|
|
e336be |
unsigned int npwm;
|
|
|
e336be |
unsigned long base_unit_bits;
|
|
|
e336be |
bool bypass;
|
|
|
e336be |
+ /* Some devices have AML code messing with the state underneath us */
|
|
|
e336be |
+ bool check_power_on_resume;
|
|
|
e336be |
};
|
|
|
e336be |
|
|
|
e336be |
struct pwm_lpss_chip *pwm_lpss_probe(struct device *dev, struct resource *r,
|
|
|
e336be |
--
|
|
|
e336be |
2.19.1
|
|
|
e336be |
|
|
|
e336be |
From 0a2e85765305e9fc376d0153aa9747b5d58cc804 Mon Sep 17 00:00:00 2001
|
|
|
e336be |
From: Hans de Goede <hdegoede@redhat.com>
|
|
|
e336be |
Date: Mon, 24 Sep 2018 20:57:43 +0200
|
|
|
e336be |
Subject: [PATCH 4/7] pwm: lpss: Release runtime-pm reference from the driver's
|
|
|
e336be |
remove callback
|
|
|
e336be |
|
|
|
e336be |
For each pwm output which gets enabled through pwm_lpss_apply(), we do a
|
|
|
e336be |
pm_runtime_get_sync().
|
|
|
e336be |
|
|
|
e336be |
This commit adds pm_runtime_put() calls to pwm_lpss_remove() to balance
|
|
|
e336be |
these when the driver gets removed with some of the outputs still enabled.
|
|
|
e336be |
|
|
|
e336be |
Fixes: f080be27d7d9 ("pwm: lpss: Add support for runtime PM")
|
|
|
e336be |
Acked-by: Andy Shevchenko <andriy.shevchenko@linux.intel.com>
|
|
|
e336be |
Signed-off-by: Hans de Goede <hdegoede@redhat.com>
|
|
|
e336be |
---
|
|
|
e336be |
Changes in v2:
|
|
|
e336be |
-New patch in v2 of this patch-set replacing "pwm: lpss: Add
|
|
|
e336be |
pwm_lpss_get_put_runtime_pm helper function"
|
|
|
e336be |
---
|
|
|
e336be |
drivers/pwm/pwm-lpss.c | 6 ++++++
|
|
|
e336be |
1 file changed, 6 insertions(+)
|
|
|
e336be |
|
|
|
e336be |
diff --git a/drivers/pwm/pwm-lpss.c b/drivers/pwm/pwm-lpss.c
|
|
|
e336be |
index e602835fd6de..723ca9de8325 100644
|
|
|
e336be |
--- a/drivers/pwm/pwm-lpss.c
|
|
|
e336be |
+++ b/drivers/pwm/pwm-lpss.c
|
|
|
e336be |
@@ -205,6 +205,12 @@ EXPORT_SYMBOL_GPL(pwm_lpss_probe);
|
|
|
e336be |
|
|
|
e336be |
int pwm_lpss_remove(struct pwm_lpss_chip *lpwm)
|
|
|
e336be |
{
|
|
|
e336be |
+ int i;
|
|
|
e336be |
+
|
|
|
e336be |
+ for (i = 0; i < lpwm->info->npwm; i++) {
|
|
|
e336be |
+ if (pwm_is_enabled(&lpwm->chip.pwms[i]))
|
|
|
e336be |
+ pm_runtime_put(lpwm->chip.dev);
|
|
|
e336be |
+ }
|
|
|
e336be |
return pwmchip_remove(&lpwm->chip);
|
|
|
e336be |
}
|
|
|
e336be |
EXPORT_SYMBOL_GPL(pwm_lpss_remove);
|
|
|
e336be |
--
|
|
|
e336be |
2.19.1
|
|
|
e336be |
|
|
|
e336be |
From c3ffc28eeb4f9974380c4a85abfbb387d6d1cd8d Mon Sep 17 00:00:00 2001
|
|
|
e336be |
From: Hans de Goede <hdegoede@redhat.com>
|
|
|
e336be |
Date: Fri, 25 Nov 2016 09:45:19 +0100
|
|
|
e336be |
Subject: [PATCH 5/7] pwm: lpss: Add get_state callback
|
|
|
e336be |
|
|
|
e336be |
Add a get_state callback so that the initial state correctly reflects
|
|
|
e336be |
the actual hardware state.
|
|
|
e336be |
|
|
|
e336be |
Cc: Andy Shevchenko <andriy.shevchenko@linux.intel.com>
|
|
|
e336be |
Acked-by: Jani Nikula <jani.nikula@intel.com>
|
|
|
e336be |
Reviewed-by: Andy Shevchenko <andriy.shevchenko@linux.intel.com>
|
|
|
e336be |
Signed-off-by: Hans de Goede <hdegoede@redhat.com>
|
|
|
e336be |
---
|
|
|
e336be |
Changes in v2:
|
|
|
e336be |
-Stop using the dropped pwm_lpss_get_put_runtime_pm() helper
|
|
|
e336be |
---
|
|
|
e336be |
drivers/pwm/pwm-lpss.c | 34 ++++++++++++++++++++++++++++++++++
|
|
|
e336be |
1 file changed, 34 insertions(+)
|
|
|
e336be |
|
|
|
e336be |
diff --git a/drivers/pwm/pwm-lpss.c b/drivers/pwm/pwm-lpss.c
|
|
|
e336be |
index 723ca9de8325..ea93ef9f3672 100644
|
|
|
e336be |
--- a/drivers/pwm/pwm-lpss.c
|
|
|
e336be |
+++ b/drivers/pwm/pwm-lpss.c
|
|
|
e336be |
@@ -159,8 +159,42 @@ static int pwm_lpss_apply(struct pwm_chip *chip, struct pwm_device *pwm,
|
|
|
e336be |
return 0;
|
|
|
e336be |
}
|
|
|
e336be |
|
|
|
e336be |
+/* This function gets called once from pwmchip_add to get the initial state */
|
|
|
e336be |
+static void pwm_lpss_get_state(struct pwm_chip *chip, struct pwm_device *pwm,
|
|
|
e336be |
+ struct pwm_state *state)
|
|
|
e336be |
+{
|
|
|
e336be |
+ struct pwm_lpss_chip *lpwm = to_lpwm(chip);
|
|
|
e336be |
+ unsigned long base_unit_range;
|
|
|
e336be |
+ unsigned long long base_unit, freq, on_time_div;
|
|
|
e336be |
+ u32 ctrl;
|
|
|
e336be |
+
|
|
|
e336be |
+ base_unit_range = BIT(lpwm->info->base_unit_bits);
|
|
|
e336be |
+
|
|
|
e336be |
+ ctrl = pwm_lpss_read(pwm);
|
|
|
e336be |
+ on_time_div = 255 - (ctrl & PWM_ON_TIME_DIV_MASK);
|
|
|
e336be |
+ base_unit = (ctrl >> PWM_BASE_UNIT_SHIFT) & (base_unit_range - 1);
|
|
|
e336be |
+
|
|
|
e336be |
+ freq = base_unit * lpwm->info->clk_rate;
|
|
|
e336be |
+ do_div(freq, base_unit_range);
|
|
|
e336be |
+ if (freq == 0)
|
|
|
e336be |
+ state->period = NSEC_PER_SEC;
|
|
|
e336be |
+ else
|
|
|
e336be |
+ state->period = NSEC_PER_SEC / (unsigned long)freq;
|
|
|
e336be |
+
|
|
|
e336be |
+ on_time_div *= state->period;
|
|
|
e336be |
+ do_div(on_time_div, 255);
|
|
|
e336be |
+ state->duty_cycle = on_time_div;
|
|
|
e336be |
+
|
|
|
e336be |
+ state->polarity = PWM_POLARITY_NORMAL;
|
|
|
e336be |
+ state->enabled = !!(ctrl & PWM_ENABLE);
|
|
|
e336be |
+
|
|
|
e336be |
+ if (state->enabled)
|
|
|
e336be |
+ pm_runtime_get(chip->dev);
|
|
|
e336be |
+}
|
|
|
e336be |
+
|
|
|
e336be |
static const struct pwm_ops pwm_lpss_ops = {
|
|
|
e336be |
.apply = pwm_lpss_apply,
|
|
|
e336be |
+ .get_state = pwm_lpss_get_state,
|
|
|
e336be |
.owner = THIS_MODULE,
|
|
|
e336be |
};
|
|
|
e336be |
|
|
|
e336be |
--
|
|
|
e336be |
2.19.1
|
|
|
e336be |
|
|
|
e336be |
From e96509f196d1229cf66b19ad9f3d7cd43a86bc9d Mon Sep 17 00:00:00 2001
|
|
|
e336be |
From: Hans de Goede <hdegoede@redhat.com>
|
|
|
e336be |
Date: Sat, 13 Oct 2018 00:04:12 +0200
|
|
|
e336be |
Subject: [PATCH 6/7] pwm: lpss: Force runtime-resume on suspend on Cherry
|
|
|
e336be |
Trail
|
|
|
e336be |
|
|
|
e336be |
On Cherry Trail devices under Windows the PWM controller used for the
|
|
|
e336be |
backlight is considered part of the GPU even though it is part of the LPSS
|
|
|
e336be |
block and thus is an entirely different independent hardware unit.
|
|
|
e336be |
|
|
|
e336be |
Because of this on Cherry Trail the GPU's (GFX0 ACPI node) _PS3 and _PS0
|
|
|
e336be |
methods save and restore the PWM controller registers.
|
|
|
e336be |
|
|
|
e336be |
If userspace blanks the screen before suspending, such as e.g. GNOME
|
|
|
e336be |
does, then the PWM controller will be runtime-suspended when the suspend
|
|
|
e336be |
starts. This causes the GFX0 _PS? methods to save a value of 0xffffffff
|
|
|
e336be |
for the PWM control register and to restore this value on resume.
|
|
|
e336be |
|
|
|
e336be |
0xffffffff is not a valid value for the register and writing this causes
|
|
|
e336be |
problems such as e.g. a flickering backlight.
|
|
|
e336be |
|
|
|
e336be |
This commit adds a prepare method to the dev_pm_ops and makes it return 0
|
|
|
e336be |
on Cherry Trail devices forcing a runtime-resume before other device's
|
|
|
e336be |
suspend methods run. This fixes the reading and writing back of 0xffffffff.
|
|
|
e336be |
|
|
|
e336be |
Since we now always runtime-resume the device on suspend, it will be
|
|
|
e336be |
resumed on resume too and we no longer need to check for the GFX0 _PS0
|
|
|
e336be |
method having resumed it underneath us, so this commit removes the now no
|
|
|
e336be |
longer necessary complete dev_pm_op.
|
|
|
e336be |
|
|
|
e336be |
Signed-off-by: Hans de Goede <hdegoede@redhat.com>
|
|
|
e336be |
---
|
|
|
e336be |
drivers/pwm/pwm-lpss-platform.c | 24 +++++++++++-------------
|
|
|
e336be |
drivers/pwm/pwm-lpss.h | 7 +++++--
|
|
|
e336be |
2 files changed, 16 insertions(+), 15 deletions(-)
|
|
|
e336be |
|
|
|
e336be |
diff --git a/drivers/pwm/pwm-lpss-platform.c b/drivers/pwm/pwm-lpss-platform.c
|
|
|
e336be |
index b6edf8af26cc..757230e1f575 100644
|
|
|
e336be |
--- a/drivers/pwm/pwm-lpss-platform.c
|
|
|
e336be |
+++ b/drivers/pwm/pwm-lpss-platform.c
|
|
|
e336be |
@@ -30,7 +30,7 @@ static const struct pwm_lpss_boardinfo pwm_lpss_bsw_info = {
|
|
|
e336be |
.clk_rate = 19200000,
|
|
|
e336be |
.npwm = 1,
|
|
|
e336be |
.base_unit_bits = 16,
|
|
|
e336be |
- .check_power_on_resume = true,
|
|
|
e336be |
+ .other_devices_aml_touches_pwm_regs = true,
|
|
|
e336be |
};
|
|
|
e336be |
|
|
|
e336be |
/* Broxton */
|
|
|
e336be |
@@ -61,6 +61,7 @@ static int pwm_lpss_probe_platform(struct platform_device *pdev)
|
|
|
e336be |
|
|
|
e336be |
platform_set_drvdata(pdev, lpwm);
|
|
|
e336be |
|
|
|
e336be |
+ dev_pm_set_driver_flags(&pdev->dev, DPM_FLAG_SMART_PREPARE);
|
|
|
e336be |
pm_runtime_set_active(&pdev->dev);
|
|
|
e336be |
pm_runtime_enable(&pdev->dev);
|
|
|
e336be |
|
|
|
e336be |
@@ -75,25 +76,22 @@ static int pwm_lpss_remove_platform(struct platform_device *pdev)
|
|
|
e336be |
return pwm_lpss_remove(lpwm);
|
|
|
e336be |
}
|
|
|
e336be |
|
|
|
e336be |
-static void pwm_lpss_complete(struct device *dev)
|
|
|
e336be |
+static int pwm_lpss_prepare(struct device *dev)
|
|
|
e336be |
{
|
|
|
e336be |
struct pwm_lpss_chip *lpwm = dev_get_drvdata(dev);
|
|
|
e336be |
- int ret, state;
|
|
|
e336be |
|
|
|
e336be |
- /* The PWM may be turned on by AML code, update our state to match */
|
|
|
e336be |
- if (pm_runtime_suspended(dev) && lpwm->info->check_power_on_resume) {
|
|
|
e336be |
- pm_runtime_disable(dev);
|
|
|
e336be |
+ /*
|
|
|
e336be |
+ * If other device's AML code touches the PWM regs on suspend/resume
|
|
|
e336be |
+ * force runtime-resume the PWM controller to allow this.
|
|
|
e336be |
+ */
|
|
|
e336be |
+ if (lpwm->info->other_devices_aml_touches_pwm_regs)
|
|
|
e336be |
+ return 0; /* Force runtime-resume */
|
|
|
e336be |
|
|
|
e336be |
- ret = acpi_device_get_power(ACPI_COMPANION(dev), &state);
|
|
|
e336be |
- if (ret == 0 && state == ACPI_STATE_D0)
|
|
|
e336be |
- pm_runtime_set_active(dev);
|
|
|
e336be |
-
|
|
|
e336be |
- pm_runtime_enable(dev);
|
|
|
e336be |
- }
|
|
|
e336be |
+ return 1; /* If runtime-suspended leave as is */
|
|
|
e336be |
}
|
|
|
e336be |
|
|
|
e336be |
static const struct dev_pm_ops pwm_lpss_platform_pm_ops = {
|
|
|
e336be |
- .complete = pwm_lpss_complete,
|
|
|
e336be |
+ .prepare = pwm_lpss_prepare,
|
|
|
e336be |
SET_SYSTEM_SLEEP_PM_OPS(pwm_lpss_suspend, pwm_lpss_resume)
|
|
|
e336be |
};
|
|
|
e336be |
|
|
|
e336be |
diff --git a/drivers/pwm/pwm-lpss.h b/drivers/pwm/pwm-lpss.h
|
|
|
e336be |
index 1a2575d25bea..3236be835bd9 100644
|
|
|
e336be |
--- a/drivers/pwm/pwm-lpss.h
|
|
|
e336be |
+++ b/drivers/pwm/pwm-lpss.h
|
|
|
e336be |
@@ -30,8 +30,11 @@ struct pwm_lpss_boardinfo {
|
|
|
e336be |
unsigned int npwm;
|
|
|
e336be |
unsigned long base_unit_bits;
|
|
|
e336be |
bool bypass;
|
|
|
e336be |
- /* Some devices have AML code messing with the state underneath us */
|
|
|
e336be |
- bool check_power_on_resume;
|
|
|
e336be |
+ /*
|
|
|
e336be |
+ * On some devices the _PS0/_PS3 AML code of the GPU (GFX0) device
|
|
|
e336be |
+ * messes with the PWM0 controllers state,
|
|
|
e336be |
+ */
|
|
|
e336be |
+ bool other_devices_aml_touches_pwm_regs;
|
|
|
e336be |
};
|
|
|
e336be |
|
|
|
e336be |
struct pwm_lpss_chip *pwm_lpss_probe(struct device *dev, struct resource *r,
|
|
|
e336be |
--
|
|
|
e336be |
2.19.1
|
|
|
e336be |
|
|
|
e336be |
From f249418a3a4f123a37c389378f289a7baea95332 Mon Sep 17 00:00:00 2001
|
|
|
e336be |
From: Hans de Goede <hdegoede@redhat.com>
|
|
|
e336be |
Date: Fri, 12 Oct 2018 21:39:53 +0200
|
|
|
e336be |
Subject: [PATCH 7/7] pwm: lpss: Only set update bit if we are actually
|
|
|
e336be |
changing the settings
|
|
|
e336be |
|
|
|
e336be |
According to the datasheet the update bit must be set if the on-time-div
|
|
|
e336be |
or the base-unit changes.
|
|
|
e336be |
|
|
|
e336be |
Now that we properly order device resume on Cherry Trail so that the GFX0
|
|
|
e336be |
_PS0 method no longer exits with an error, we end up with a sequence of
|
|
|
e336be |
events where we are writing the same values twice in a row.
|
|
|
e336be |
|
|
|
e336be |
First the _PS0 method restores the duty cycle of 0% the GPU driver set
|
|
|
e336be |
on suspend and then the GPU driver first updates just the enabled bit in
|
|
|
e336be |
the pwm_state from 0 to 1, causing us to write the same values again,
|
|
|
e336be |
before restoring the pre-suspend duty-cycle in a separate pwm_apply call.
|
|
|
e336be |
|
|
|
e336be |
When writing the update bit the second time, without changing any of
|
|
|
e336be |
the values the update bit clears immediately / instantly, instead of
|
|
|
e336be |
staying 1 for a while as usual. After this the next setting of the update
|
|
|
e336be |
bit seems to be ignored, causing the restoring of the pre-suspend
|
|
|
e336be |
duty-cycle to not get applied. This makes the backlight come up with
|
|
|
e336be |
a 0% dutycycle after suspend/resume.
|
|
|
e336be |
|
|
|
e336be |
Any further brightness changes after this do work.
|
|
|
e336be |
|
|
|
e336be |
This commit moves the setting of the update bit into pwm_lpss_prepare()
|
|
|
e336be |
and only sets the bit if we have actually changed any of the values.
|
|
|
e336be |
|
|
|
e336be |
This avoids the setting of the update bit the second time we configure
|
|
|
e336be |
the PWM to 0% dutycycle, this fixes the backlight coming up with 0%
|
|
|
e336be |
duty-cycle after a suspend/resume.
|
|
|
e336be |
|
|
|
e336be |
Signed-off-by: Hans de Goede <hdegoede@redhat.com>
|
|
|
e336be |
---
|
|
|
e336be |
drivers/pwm/pwm-lpss.c | 12 +++++++-----
|
|
|
e336be |
1 file changed, 7 insertions(+), 5 deletions(-)
|
|
|
e336be |
|
|
|
e336be |
diff --git a/drivers/pwm/pwm-lpss.c b/drivers/pwm/pwm-lpss.c
|
|
|
e336be |
index ea93ef9f3672..2ac3a2aa9e53 100644
|
|
|
e336be |
--- a/drivers/pwm/pwm-lpss.c
|
|
|
e336be |
+++ b/drivers/pwm/pwm-lpss.c
|
|
|
e336be |
@@ -88,7 +88,7 @@ static void pwm_lpss_prepare(struct pwm_lpss_chip *lpwm, struct pwm_device *pwm,
|
|
|
e336be |
unsigned long long on_time_div;
|
|
|
e336be |
unsigned long c = lpwm->info->clk_rate, base_unit_range;
|
|
|
e336be |
unsigned long long base_unit, freq = NSEC_PER_SEC;
|
|
|
e336be |
- u32 ctrl;
|
|
|
e336be |
+ u32 orig_ctrl, ctrl;
|
|
|
e336be |
|
|
|
e336be |
do_div(freq, period_ns);
|
|
|
e336be |
|
|
|
e336be |
@@ -105,13 +105,17 @@ static void pwm_lpss_prepare(struct pwm_lpss_chip *lpwm, struct pwm_device *pwm,
|
|
|
e336be |
do_div(on_time_div, period_ns);
|
|
|
e336be |
on_time_div = 255ULL - on_time_div;
|
|
|
e336be |
|
|
|
e336be |
- ctrl = pwm_lpss_read(pwm);
|
|
|
e336be |
+ orig_ctrl = ctrl = pwm_lpss_read(pwm);
|
|
|
e336be |
ctrl &= ~PWM_ON_TIME_DIV_MASK;
|
|
|
e336be |
ctrl &= ~(base_unit_range << PWM_BASE_UNIT_SHIFT);
|
|
|
e336be |
base_unit &= base_unit_range;
|
|
|
e336be |
ctrl |= (u32) base_unit << PWM_BASE_UNIT_SHIFT;
|
|
|
e336be |
ctrl |= on_time_div;
|
|
|
e336be |
- pwm_lpss_write(pwm, ctrl);
|
|
|
e336be |
+
|
|
|
e336be |
+ if (orig_ctrl != ctrl) {
|
|
|
e336be |
+ pwm_lpss_write(pwm, ctrl);
|
|
|
e336be |
+ pwm_lpss_write(pwm, ctrl | PWM_SW_UPDATE);
|
|
|
e336be |
+ }
|
|
|
e336be |
}
|
|
|
e336be |
|
|
|
e336be |
static inline void pwm_lpss_cond_enable(struct pwm_device *pwm, bool cond)
|
|
|
e336be |
@@ -135,7 +139,6 @@ static int pwm_lpss_apply(struct pwm_chip *chip, struct pwm_device *pwm,
|
|
|
e336be |
return ret;
|
|
|
e336be |
}
|
|
|
e336be |
pwm_lpss_prepare(lpwm, pwm, state->duty_cycle, state->period);
|
|
|
e336be |
- pwm_lpss_write(pwm, pwm_lpss_read(pwm) | PWM_SW_UPDATE);
|
|
|
e336be |
pwm_lpss_cond_enable(pwm, lpwm->info->bypass == false);
|
|
|
e336be |
ret = pwm_lpss_wait_for_update(pwm);
|
|
|
e336be |
if (ret) {
|
|
|
e336be |
@@ -148,7 +151,6 @@ static int pwm_lpss_apply(struct pwm_chip *chip, struct pwm_device *pwm,
|
|
|
e336be |
if (ret)
|
|
|
e336be |
return ret;
|
|
|
e336be |
pwm_lpss_prepare(lpwm, pwm, state->duty_cycle, state->period);
|
|
|
e336be |
- pwm_lpss_write(pwm, pwm_lpss_read(pwm) | PWM_SW_UPDATE);
|
|
|
e336be |
return pwm_lpss_wait_for_update(pwm);
|
|
|
e336be |
}
|
|
|
e336be |
} else if (pwm_is_enabled(pwm)) {
|
|
|
e336be |
--
|
|
|
e336be |
2.19.1
|
|
|
e336be |
|