Donate to e Foundation | Murena handsets with /e/OS | Own a part of Murena! Learn more

Commit 3f3f3e7b authored by Linux Build Service Account's avatar Linux Build Service Account Committed by Gerrit - the friendly Code Review server
Browse files

Merge "ASoC: aw8896: add logic to handle regulator for DVDD"

parents 8c563904 6757b96a
Loading
Loading
Loading
Loading
+10 −1
Original line number Diff line number Diff line
@@ -8,6 +8,12 @@ Required properties:

  - 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:

  - irq-gpio: gpio used for irq indicator
@@ -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>;
	};
+84 −1
Original line number Diff line number Diff line
@@ -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 @@ static int aw8896_i2c_probe(struct i2c_client *i2c,
	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;

+9 −0
Original line number Diff line number Diff line
@@ -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;