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: Cheng-Yi Chiang <cychiang@chromium.org> Signed-off-by: Mark Brown <broonie@kernel.org>
This commit is contained in:

committed by
Mark Brown

parent
bf897b441b
commit
e81a2a6d12
@@ -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 @@
|
|||||||
#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 {
|
|||||||
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 {
|
|||||||
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,
|
|||||||
{
|
{
|
||||||
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,
|
|||||||
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,
|
|||||||
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,
|
|||||||
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)
|
|||||||
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;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
Reference in New Issue
Block a user