summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorFlorian Muller <mullerf@google.com>2022-03-19 18:13:52 -0700
committerFlorian Muller <mullerf@google.com>2022-04-19 11:17:38 -0700
commit1ad543c6bbbba6c701295ee62b538cccbc2a1d86 (patch)
treee77aba39c0d171eb61b45f9b630f3e9a9b0f4ff7
parenta30521d7964b098374a11cf534c57c84368f3c2d (diff)
downloaddrivers-1ad543c6bbbba6c701295ee62b538cccbc2a1d86.tar.gz
cs53l41: Register smart amp to s2mpw02-fuelgauge and wireless psy
This is needed so we can later add support to scale the smart amp volume according to the battery level and battery state (on vs off charger) Test: Manual Bug: 228179922 Signed-off-by: Florian Muller <mullerf@google.com> Change-Id: I1786806246d5f2838134658eacec4c39166a625a
-rw-r--r--sound/cs35l41/cs35l41.c73
-rw-r--r--sound/cs35l41/include/sound/cs35l41.h7
2 files changed, 80 insertions, 0 deletions
diff --git a/sound/cs35l41/cs35l41.c b/sound/cs35l41/cs35l41.c
index 2b172d6..9fb526d 100644
--- a/sound/cs35l41/cs35l41.c
+++ b/sound/cs35l41/cs35l41.c
@@ -41,6 +41,7 @@
#include <linux/err.h>
#include <linux/firmware.h>
#include <linux/timekeeping.h>
+#include <linux/power_supply.h>
#include "wm_adsp.h"
#include "cs35l41.h"
@@ -3440,6 +3441,41 @@ static int cs35l41_restore(struct cs35l41_private *cs35l41)
return 0;
}
+static int battery_handle_notification(struct notifier_block *nb,
+ unsigned long val, void *v)
+{
+ struct cs35l41_private *cs35l41 =
+ container_of(nb, struct cs35l41_private, batt_nb);
+ struct power_supply *psy_wlc = cs35l41->wlc_power_supply;
+ struct power_supply *psy_batt = cs35l41->batt_power_supply;
+ union power_supply_propval value;
+ int ret;
+
+ ret = power_supply_get_property(psy_wlc, POWER_SUPPLY_PROP_PRESENT, &value);
+ if (ret < 0)
+ dev_err(cs35l41->dev, "%s: Fail to execute WLC present property", __func__);
+ else
+ cs35l41->wlc_present = value.intval;
+
+ ret = power_supply_get_property(psy_batt, POWER_SUPPLY_PROP_CAPACITY, &value);
+ if (ret < 0)
+ dev_err(cs35l41->dev, "%s: Fail to execute battery capacity property", __func__);
+ else
+ cs35l41->batt_capacity = value.intval;
+
+ ret = power_supply_get_property(psy_batt, POWER_SUPPLY_PROP_STATUS, &value);
+ if (ret < 0)
+ dev_err(cs35l41->dev, "%s: Fail to execute battery status property", __func__);
+ else
+ cs35l41->batt_status = value.intval;
+
+ dev_dbg(cs35l41->dev, "%s: wlc_present: %d batt_capacity: %d batt_status:%d",
+ __func__, cs35l41->wlc_present, cs35l41->batt_capacity, cs35l41->batt_status);
+
+ return NOTIFY_OK;
+}
+
+
int cs35l41_probe(struct cs35l41_private *cs35l41,
struct cs35l41_platform_data *pdata)
{
@@ -3769,6 +3805,36 @@ int cs35l41_probe(struct cs35l41_private *cs35l41,
INIT_DELAYED_WORK(&cs35l41->hb_work, cs35l41_hibernate_work);
mutex_init(&cs35l41->hb_lock);
+
+ /************************************/
+ /* Register to battery power supply */
+ /************************************/
+ cs35l41->wlc_present = 0;
+ cs35l41->batt_capacity = 100;
+ cs35l41->batt_status = POWER_SUPPLY_STATUS_DISCHARGING;
+ cs35l41->wlc_power_supply = power_supply_get_by_name("wireless");
+ if (IS_ERR(cs35l41->wlc_power_supply) || !cs35l41->wlc_power_supply) {
+ dev_err(cs35l41->dev, "Couldn't get the wireless power supply\n");
+ } else {
+ cs35l41->batt_power_supply = power_supply_get_by_name("battery");
+ if (IS_ERR(cs35l41->batt_power_supply) || !cs35l41->batt_power_supply) {
+ dev_err(cs35l41->dev, "Couldn't get the battery power supply\n");
+ power_supply_put(cs35l41->wlc_power_supply); // Drop ref to wlc_power_supply
+ } else {
+ cs35l41->batt_nb.notifier_call = battery_handle_notification;
+ cs35l41->batt_nb.priority = 0;
+ ret = power_supply_reg_notifier(&cs35l41->batt_nb);
+ if (ret) {
+ dev_err(cs35l41->dev, "Register power_supply failed\n");
+ power_supply_put(cs35l41->wlc_power_supply); // Drop ref to wlc_power_supply
+ power_supply_put(cs35l41->batt_power_supply); // Drop ref to batt_power_supply
+ } else {
+ dev_dbg(cs35l41->dev, "Registered power_supply successfully\n");
+ cs35l41->batt_nb_registered = true;
+ }
+ }
+ }
+
err:
regulator_bulk_disable(cs35l41->num_supplies, cs35l41->supplies);
return ret;
@@ -3776,6 +3842,13 @@ err:
int cs35l41_remove(struct cs35l41_private *cs35l41)
{
+ if (cs35l41->batt_nb_registered) {
+ power_supply_unreg_notifier(&cs35l41->batt_nb);
+ power_supply_put(cs35l41->wlc_power_supply); // Drop ref to wlc_power_supply
+ power_supply_put(cs35l41->batt_power_supply); // Drop ref to batt_power_supply
+ cs35l41->batt_nb_registered = false;
+ }
+
destroy_workqueue(cs35l41->wq);
mutex_destroy(&cs35l41->hb_lock);
regmap_write(cs35l41->regmap, CS35L41_IRQ1_MASK1, 0xFFFFFFFF);
diff --git a/sound/cs35l41/include/sound/cs35l41.h b/sound/cs35l41/include/sound/cs35l41.h
index 352844f..b3e5c6f 100644
--- a/sound/cs35l41/include/sound/cs35l41.h
+++ b/sound/cs35l41/include/sound/cs35l41.h
@@ -128,6 +128,13 @@ struct cs35l41_private {
u32 trim_cache[CS35L41_TRIM_CACHE_SIZE];
u32 sample_rate_hz;
atomic_t is_irq_enabled;
+ struct power_supply *wlc_power_supply;
+ int wlc_present;
+ struct power_supply *batt_power_supply;
+ struct notifier_block batt_nb;
+ bool batt_nb_registered;
+ int batt_capacity;
+ int batt_status;
};
int cs35l41_probe(struct cs35l41_private *cs35l41,