Commit e81a2a6d authored by Cheng-Yi Chiang's avatar Cheng-Yi Chiang Committed by Mark Brown

ASoC: rt5663: Add regulator support

Add regulator support to turn on cpvdd and avdd in probe.
If a regulator is not given from device tree, a dummy regulator will be
used.
Signed-off-by: default avatarCheng-Yi Chiang <cychiang@chromium.org>
Signed-off-by: default avatarMark Brown <broonie@kernel.org>
parent bf897b44
...@@ -17,6 +17,7 @@ ...@@ -17,6 +17,7 @@
#include <linux/platform_device.h> #include <linux/platform_device.h>
#include <linux/spi/spi.h> #include <linux/spi/spi.h>
#include <linux/acpi.h> #include <linux/acpi.h>
#include <linux/regulator/consumer.h>
#include <linux/workqueue.h> #include <linux/workqueue.h>
#include <sound/core.h> #include <sound/core.h>
#include <sound/pcm.h> #include <sound/pcm.h>
...@@ -33,6 +34,9 @@ ...@@ -33,6 +34,9 @@
#define RT5663_DEVICE_ID_2 0x6451 #define RT5663_DEVICE_ID_2 0x6451
#define RT5663_DEVICE_ID_1 0x6406 #define RT5663_DEVICE_ID_1 0x6406
#define RT5663_POWER_ON_DELAY_MS 300
#define RT5663_SUPPLY_CURRENT_UA 500000
enum { enum {
CODEC_VER_1, CODEC_VER_1,
CODEC_VER_0, CODEC_VER_0,
...@@ -48,6 +52,11 @@ struct impedance_mapping_table { ...@@ -48,6 +52,11 @@ struct impedance_mapping_table {
unsigned int dc_offset_r_manual_mic; unsigned int dc_offset_r_manual_mic;
}; };
static const char *const rt5663_supply_names[] = {
"avdd",
"cpvdd",
};
struct rt5663_priv { struct rt5663_priv {
struct snd_soc_component *component; struct snd_soc_component *component;
struct rt5663_platform_data pdata; struct rt5663_platform_data pdata;
...@@ -56,6 +65,7 @@ struct rt5663_priv { ...@@ -56,6 +65,7 @@ struct rt5663_priv {
struct snd_soc_jack *hs_jack; struct snd_soc_jack *hs_jack;
struct timer_list btn_check_timer; struct timer_list btn_check_timer;
struct impedance_mapping_table *imp_table; struct impedance_mapping_table *imp_table;
struct regulator_bulk_data supplies[ARRAY_SIZE(rt5663_supply_names)];
int codec_ver; int codec_ver;
int sysclk; int sysclk;
...@@ -3483,7 +3493,7 @@ static int rt5663_i2c_probe(struct i2c_client *i2c, ...@@ -3483,7 +3493,7 @@ static int rt5663_i2c_probe(struct i2c_client *i2c,
{ {
struct rt5663_platform_data *pdata = dev_get_platdata(&i2c->dev); struct rt5663_platform_data *pdata = dev_get_platdata(&i2c->dev);
struct rt5663_priv *rt5663; struct rt5663_priv *rt5663;
int ret; int ret, i;
unsigned int val; unsigned int val;
struct regmap *regmap; struct regmap *regmap;
...@@ -3500,6 +3510,37 @@ static int rt5663_i2c_probe(struct i2c_client *i2c, ...@@ -3500,6 +3510,37 @@ static int rt5663_i2c_probe(struct i2c_client *i2c,
else else
rt5663_parse_dp(rt5663, &i2c->dev); rt5663_parse_dp(rt5663, &i2c->dev);
for (i = 0; i < ARRAY_SIZE(rt5663->supplies); i++)
rt5663->supplies[i].supply = rt5663_supply_names[i];
ret = devm_regulator_bulk_get(&i2c->dev,
ARRAY_SIZE(rt5663->supplies),
rt5663->supplies);
if (ret) {
dev_err(&i2c->dev, "Failed to request supplies: %d\n", ret);
return ret;
}
/* Set load for regulator. */
for (i = 0; i < ARRAY_SIZE(rt5663->supplies); i++) {
ret = regulator_set_load(rt5663->supplies[i].consumer,
RT5663_SUPPLY_CURRENT_UA);
if (ret) {
dev_err(&i2c->dev,
"Failed to set regulator %s, ret: %d\n",
rt5663->supplies[i].supply, ret);
}
}
ret = regulator_bulk_enable(ARRAY_SIZE(rt5663->supplies),
rt5663->supplies);
if (ret) {
dev_err(&i2c->dev, "Failed to enable supplies: %d\n", ret);
return ret;
}
msleep(RT5663_POWER_ON_DELAY_MS);
regmap = devm_regmap_init_i2c(i2c, &temp_regmap); regmap = devm_regmap_init_i2c(i2c, &temp_regmap);
if (IS_ERR(regmap)) { if (IS_ERR(regmap)) {
ret = PTR_ERR(regmap); ret = PTR_ERR(regmap);
...@@ -3530,7 +3571,8 @@ static int rt5663_i2c_probe(struct i2c_client *i2c, ...@@ -3530,7 +3571,8 @@ static int rt5663_i2c_probe(struct i2c_client *i2c,
dev_err(&i2c->dev, dev_err(&i2c->dev,
"Device with ID register %#x is not rt5663\n", "Device with ID register %#x is not rt5663\n",
val); val);
return -ENODEV; ret = -ENODEV;
goto err_enable;
} }
if (IS_ERR(rt5663->regmap)) { if (IS_ERR(rt5663->regmap)) {
...@@ -3635,20 +3677,30 @@ static int rt5663_i2c_probe(struct i2c_client *i2c, ...@@ -3635,20 +3677,30 @@ static int rt5663_i2c_probe(struct i2c_client *i2c,
ret = request_irq(i2c->irq, rt5663_irq, ret = request_irq(i2c->irq, rt5663_irq,
IRQF_TRIGGER_RISING | IRQF_TRIGGER_FALLING IRQF_TRIGGER_RISING | IRQF_TRIGGER_FALLING
| IRQF_ONESHOT, "rt5663", rt5663); | IRQF_ONESHOT, "rt5663", rt5663);
if (ret) if (ret) {
dev_err(&i2c->dev, "%s Failed to reguest IRQ: %d\n", dev_err(&i2c->dev, "%s Failed to reguest IRQ: %d\n",
__func__, ret); __func__, ret);
goto err_enable;
}
} }
ret = devm_snd_soc_register_component(&i2c->dev, ret = devm_snd_soc_register_component(&i2c->dev,
&soc_component_dev_rt5663, &soc_component_dev_rt5663,
rt5663_dai, ARRAY_SIZE(rt5663_dai)); rt5663_dai, ARRAY_SIZE(rt5663_dai));
if (ret) { if (ret)
if (i2c->irq) goto err_irq;
free_irq(i2c->irq, rt5663);
}
return 0;
err_irq:
if (i2c->irq)
free_irq(i2c->irq, rt5663);
err_enable:
dev_err(&i2c->dev,
"%s: Disable regulator after probe error\n", __func__);
regulator_bulk_disable(ARRAY_SIZE(rt5663->supplies), rt5663->supplies);
return ret; return ret;
} }
...@@ -3659,6 +3711,8 @@ static int rt5663_i2c_remove(struct i2c_client *i2c) ...@@ -3659,6 +3711,8 @@ static int rt5663_i2c_remove(struct i2c_client *i2c)
if (i2c->irq) if (i2c->irq)
free_irq(i2c->irq, rt5663); free_irq(i2c->irq, rt5663);
regulator_bulk_disable(ARRAY_SIZE(rt5663->supplies), rt5663->supplies);
return 0; return 0;
} }
......
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment