ASoC: aw8896: add logic to handle regulator for DVDD
aw8896's DVDD is not powered by default, add logic to read regulator info from device tree, and enable power for DVDD in the driver probe function. Change-Id: I544ef3e8e7f273f868cefc6a3ff27b6e7f9ed768 Signed-off-by: Xiao Li <lixiao@codeaurora.org>
This commit is contained in:
parent
34f2473afc
commit
6757b96a51
|
@ -6,7 +6,13 @@ Required properties:
|
|||
|
||||
- reg : I2C address of the device
|
||||
|
||||
- reset-gpio: gpio used for HW reset
|
||||
- reset-gpio : gpio used for HW reset
|
||||
|
||||
- dvdd-supply : Power supply for PA's dvdd
|
||||
|
||||
- dvdd-voltage : Minimum and maximum voltage in uV to set for power supply
|
||||
|
||||
- dvdd-current : dvdd's max current in uA
|
||||
|
||||
Optional properties:
|
||||
|
||||
|
@ -18,4 +24,7 @@ Examples:
|
|||
compatible = "awinic,i2c_smartpa";
|
||||
reg = <0x34>;
|
||||
reset-gpio = <&tlmm 68 0>;
|
||||
dvdd-supply = <&pm660_l9>;
|
||||
dvdd-voltage = <1800000 1800000>;
|
||||
dvdd-current = <15000>;
|
||||
};
|
||||
|
|
|
@ -43,6 +43,7 @@
|
|||
#define AW_READ_CHIPID_RETRIES 5
|
||||
#define AW_READ_CHIPID_RETRY_DELAY 5
|
||||
#define AW8896_MAX_DSP_START_TRY_COUNT 10
|
||||
#define DT_MAX_PROP_SIZE 80
|
||||
|
||||
static int aw8896_spk_control;
|
||||
static int aw8896_rcv_control;
|
||||
|
@ -1068,6 +1069,14 @@ static irqreturn_t aw8896_irq(int irq, void *data)
|
|||
|
||||
static int aw8896_parse_dt(struct device *dev, struct aw8896 *aw8896,
|
||||
struct device_node *np) {
|
||||
int prop_val = 0;
|
||||
int ret = 0;
|
||||
int len = 0;
|
||||
const __be32 *prop = NULL;
|
||||
struct device_node *regnode = NULL;
|
||||
char *dvdd_supply = "dvdd";
|
||||
char prop_name[DT_MAX_PROP_SIZE] = {0};
|
||||
|
||||
aw8896->reset_gpio = of_get_named_gpio(np, "reset-gpio", 0);
|
||||
if (aw8896->reset_gpio < 0) {
|
||||
dev_err(dev,
|
||||
|
@ -1082,7 +1091,47 @@ static int aw8896_parse_dt(struct device *dev, struct aw8896 *aw8896,
|
|||
if (aw8896->irq_gpio < 0)
|
||||
dev_info(dev, "%s: no irq gpio provided.\n", __func__);
|
||||
|
||||
snprintf(prop_name, DT_MAX_PROP_SIZE, "%s-supply", dvdd_supply);
|
||||
regnode = of_parse_phandle(np, prop_name, 0);
|
||||
if (!regnode) {
|
||||
dev_err(dev, "%s: no %s provided\n", __func__, prop_name);
|
||||
goto err_get_regulator;
|
||||
}
|
||||
|
||||
aw8896->supply.regulator = devm_regulator_get(dev, dvdd_supply);
|
||||
if (IS_ERR(aw8896->supply.regulator)) {
|
||||
dev_err(dev, "%s: failed to get supply for %s\n", __func__,
|
||||
dvdd_supply);
|
||||
goto err_get_regulator;
|
||||
}
|
||||
|
||||
snprintf(prop_name, DT_MAX_PROP_SIZE, "%s-voltage", dvdd_supply);
|
||||
prop = of_get_property(np, prop_name, &len);
|
||||
if (!prop || (len != (2 * sizeof(__be32)))) {
|
||||
dev_err(dev, "%s: no %s provided or format invalid\n",
|
||||
__func__, prop_name);
|
||||
goto err_get_voltage;
|
||||
}
|
||||
|
||||
aw8896->supply.min_uv = be32_to_cpup(&prop[0]);
|
||||
aw8896->supply.max_uv = be32_to_cpup(&prop[1]);
|
||||
|
||||
snprintf(prop_name, DT_MAX_PROP_SIZE, "%s-current", dvdd_supply);
|
||||
ret = of_property_read_u32(np, prop_name, &prop_val);
|
||||
if (ret) {
|
||||
dev_err(dev, "%s: no %s provided\n", __func__, prop_name);
|
||||
goto err_get_current;
|
||||
}
|
||||
aw8896->supply.ua = prop_val;
|
||||
|
||||
return 0;
|
||||
|
||||
err_get_current:
|
||||
err_get_voltage:
|
||||
devm_regulator_put(aw8896->supply.regulator);
|
||||
aw8896->supply.regulator = NULL;
|
||||
err_get_regulator:
|
||||
return -EINVAL;
|
||||
}
|
||||
|
||||
int aw8896_hw_reset(struct aw8896 *aw8896)
|
||||
|
@ -1354,7 +1403,7 @@ static int aw8896_i2c_probe(struct i2c_client *i2c,
|
|||
|
||||
i2c_set_clientdata(i2c, aw8896);
|
||||
mutex_init(&aw8896->lock);
|
||||
/* aw8896 rst & int */
|
||||
|
||||
if (np) {
|
||||
ret = aw8896_parse_dt(&i2c->dev, aw8896, np);
|
||||
if (ret) {
|
||||
|
@ -1388,6 +1437,30 @@ static int aw8896_i2c_probe(struct i2c_client *i2c,
|
|||
}
|
||||
}
|
||||
|
||||
ret = regulator_set_voltage(aw8896->supply.regulator,
|
||||
aw8896->supply.max_uv,
|
||||
aw8896->supply.min_uv);
|
||||
if (ret) {
|
||||
dev_err(&i2c->dev, "%s: set voltage %d ~ %d failed\n",
|
||||
__func__,
|
||||
aw8896->supply.min_uv,
|
||||
aw8896->supply.max_uv);
|
||||
goto err_supply_set;
|
||||
}
|
||||
|
||||
ret = regulator_set_load(aw8896->supply.regulator, aw8896->supply.ua);
|
||||
if (ret < 0) {
|
||||
dev_err(&i2c->dev, "%s: set current %d failed\n", __func__,
|
||||
aw8896->supply.ua);
|
||||
goto err_supply_set;
|
||||
}
|
||||
|
||||
ret = regulator_enable(aw8896->supply.regulator);
|
||||
if (ret < 0) {
|
||||
dev_err(&i2c->dev, "%s: regulator enable failed\n", __func__);
|
||||
goto err_supply_set;
|
||||
}
|
||||
|
||||
ret = aw8896_hw_reset(aw8896);
|
||||
if (ret < 0) {
|
||||
dev_err(&i2c->dev, "%s: aw8896_hw_reset failed\n", __func__);
|
||||
|
@ -1461,6 +1534,11 @@ err_id:
|
|||
if (gpio_is_valid(aw8896->irq_gpio))
|
||||
devm_gpio_free(&i2c->dev, aw8896->irq_gpio);
|
||||
err_hw_rst:
|
||||
if (aw8896->supply.regulator)
|
||||
regulator_disable(aw8896->supply.regulator);
|
||||
err_supply_set:
|
||||
if (aw8896->supply.regulator)
|
||||
devm_regulator_put(aw8896->supply.regulator);
|
||||
err_irq_gpio_request:
|
||||
if (gpio_is_valid(aw8896->reset_gpio))
|
||||
devm_gpio_free(&i2c->dev, aw8896->reset_gpio);
|
||||
|
@ -1486,6 +1564,11 @@ static int aw8896_i2c_remove(struct i2c_client *i2c)
|
|||
if (gpio_is_valid(aw8896->reset_gpio))
|
||||
devm_gpio_free(&i2c->dev, aw8896->reset_gpio);
|
||||
|
||||
if (aw8896->supply.regulator) {
|
||||
regulator_disable(aw8896->supply.regulator);
|
||||
devm_regulator_put(aw8896->supply.regulator);
|
||||
}
|
||||
|
||||
devm_kfree(&i2c->dev, aw8896);
|
||||
aw8896 = NULL;
|
||||
|
||||
|
|
|
@ -15,6 +15,7 @@
|
|||
|
||||
#ifndef _AW8896_H_
|
||||
#define _AW8896_H_
|
||||
#include <linux/regulator/driver.h>
|
||||
|
||||
/*
|
||||
* i2c transaction on Linux limited to 64k
|
||||
|
@ -81,10 +82,18 @@ enum aw8896_dsp_cfg_state {
|
|||
AW8896_DSP_CFG_OK,
|
||||
};
|
||||
|
||||
struct dvdd_supply {
|
||||
struct regulator *regulator;
|
||||
int min_uv;
|
||||
int max_uv;
|
||||
int ua;
|
||||
};
|
||||
|
||||
struct aw8896 {
|
||||
struct regmap *regmap;
|
||||
struct i2c_client *i2c;
|
||||
struct snd_soc_codec *codec;
|
||||
struct dvdd_supply supply;
|
||||
struct mutex lock;
|
||||
int dsp_init;
|
||||
int dsp_fw_state;
|
||||
|
|
Loading…
Reference in New Issue