ASoC: tap6130a2: Use regmap
Use regmap instead of open-coding IO access and caching Signed-off-by: Lars-Peter Clausen <lars@metafoo.de> [koike: port for upstream] Signed-off-by: Helen Koike <helen.koike@collabora.co.uk> [On N900] Tested-By: Sebastian Reichel <sre@kernel.org> Reviewed-By: Sebastian Reichel <sre@kernel.org> Signed-off-by: Mark Brown <broonie@kernel.org>
This commit is contained in:
Родитель
cb7e62256e
Коммит
a0d5ff4496
|
@ -32,6 +32,7 @@
|
||||||
#include <sound/tlv.h>
|
#include <sound/tlv.h>
|
||||||
#include <linux/of.h>
|
#include <linux/of.h>
|
||||||
#include <linux/of_gpio.h>
|
#include <linux/of_gpio.h>
|
||||||
|
#include <linux/regmap.h>
|
||||||
|
|
||||||
#include "tpa6130a2.h"
|
#include "tpa6130a2.h"
|
||||||
|
|
||||||
|
@ -45,92 +46,16 @@ static struct i2c_client *tpa6130a2_client;
|
||||||
/* This struct is used to save the context */
|
/* This struct is used to save the context */
|
||||||
struct tpa6130a2_data {
|
struct tpa6130a2_data {
|
||||||
struct mutex mutex;
|
struct mutex mutex;
|
||||||
unsigned char regs[TPA6130A2_CACHEREGNUM];
|
struct regmap *regmap;
|
||||||
struct regulator *supply;
|
struct regulator *supply;
|
||||||
int power_gpio;
|
int power_gpio;
|
||||||
u8 power_state:1;
|
u8 power_state:1;
|
||||||
enum tpa_model id;
|
enum tpa_model id;
|
||||||
};
|
};
|
||||||
|
|
||||||
static int tpa6130a2_i2c_read(int reg)
|
|
||||||
{
|
|
||||||
struct tpa6130a2_data *data;
|
|
||||||
int val;
|
|
||||||
|
|
||||||
if (WARN_ON(!tpa6130a2_client))
|
|
||||||
return -EINVAL;
|
|
||||||
data = i2c_get_clientdata(tpa6130a2_client);
|
|
||||||
|
|
||||||
/* If powered off, return the cached value */
|
|
||||||
if (data->power_state) {
|
|
||||||
val = i2c_smbus_read_byte_data(tpa6130a2_client, reg);
|
|
||||||
if (val < 0)
|
|
||||||
dev_err(&tpa6130a2_client->dev, "Read failed\n");
|
|
||||||
else
|
|
||||||
data->regs[reg] = val;
|
|
||||||
} else {
|
|
||||||
val = data->regs[reg];
|
|
||||||
}
|
|
||||||
|
|
||||||
return val;
|
|
||||||
}
|
|
||||||
|
|
||||||
static int tpa6130a2_i2c_write(int reg, u8 value)
|
|
||||||
{
|
|
||||||
struct tpa6130a2_data *data;
|
|
||||||
int val = 0;
|
|
||||||
|
|
||||||
if (WARN_ON(!tpa6130a2_client))
|
|
||||||
return -EINVAL;
|
|
||||||
data = i2c_get_clientdata(tpa6130a2_client);
|
|
||||||
|
|
||||||
if (data->power_state) {
|
|
||||||
val = i2c_smbus_write_byte_data(tpa6130a2_client, reg, value);
|
|
||||||
if (val < 0) {
|
|
||||||
dev_err(&tpa6130a2_client->dev, "Write failed\n");
|
|
||||||
return val;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
/* Either powered on or off, we save the context */
|
|
||||||
data->regs[reg] = value;
|
|
||||||
|
|
||||||
return val;
|
|
||||||
}
|
|
||||||
|
|
||||||
static u8 tpa6130a2_read(int reg)
|
|
||||||
{
|
|
||||||
struct tpa6130a2_data *data;
|
|
||||||
|
|
||||||
if (WARN_ON(!tpa6130a2_client))
|
|
||||||
return 0;
|
|
||||||
data = i2c_get_clientdata(tpa6130a2_client);
|
|
||||||
|
|
||||||
return data->regs[reg];
|
|
||||||
}
|
|
||||||
|
|
||||||
static int tpa6130a2_initialize(void)
|
|
||||||
{
|
|
||||||
struct tpa6130a2_data *data;
|
|
||||||
int i, ret = 0;
|
|
||||||
|
|
||||||
if (WARN_ON(!tpa6130a2_client))
|
|
||||||
return -EINVAL;
|
|
||||||
data = i2c_get_clientdata(tpa6130a2_client);
|
|
||||||
|
|
||||||
for (i = 1; i < TPA6130A2_REG_VERSION; i++) {
|
|
||||||
ret = tpa6130a2_i2c_write(i, data->regs[i]);
|
|
||||||
if (ret < 0)
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
|
|
||||||
return ret;
|
|
||||||
}
|
|
||||||
|
|
||||||
static int tpa6130a2_power(u8 power)
|
static int tpa6130a2_power(u8 power)
|
||||||
{
|
{
|
||||||
struct tpa6130a2_data *data;
|
struct tpa6130a2_data *data;
|
||||||
u8 val;
|
|
||||||
int ret = 0;
|
int ret = 0;
|
||||||
|
|
||||||
if (WARN_ON(!tpa6130a2_client))
|
if (WARN_ON(!tpa6130a2_client))
|
||||||
|
@ -153,7 +78,7 @@ static int tpa6130a2_power(u8 power)
|
||||||
gpio_set_value(data->power_gpio, 1);
|
gpio_set_value(data->power_gpio, 1);
|
||||||
|
|
||||||
data->power_state = 1;
|
data->power_state = 1;
|
||||||
ret = tpa6130a2_initialize();
|
ret = regcache_sync(data->regmap);
|
||||||
if (ret < 0) {
|
if (ret < 0) {
|
||||||
dev_err(&tpa6130a2_client->dev,
|
dev_err(&tpa6130a2_client->dev,
|
||||||
"Failed to initialize chip\n");
|
"Failed to initialize chip\n");
|
||||||
|
@ -165,9 +90,8 @@ static int tpa6130a2_power(u8 power)
|
||||||
}
|
}
|
||||||
} else {
|
} else {
|
||||||
/* set SWS */
|
/* set SWS */
|
||||||
val = tpa6130a2_read(TPA6130A2_REG_CONTROL);
|
regmap_update_bits(data->regmap, TPA6130A2_REG_CONTROL,
|
||||||
val |= TPA6130A2_SWS;
|
TPA6130A2_SWS, TPA6130A2_SWS);
|
||||||
tpa6130a2_i2c_write(TPA6130A2_REG_CONTROL, val);
|
|
||||||
|
|
||||||
/* Power off */
|
/* Power off */
|
||||||
if (data->power_gpio >= 0)
|
if (data->power_gpio >= 0)
|
||||||
|
@ -181,6 +105,8 @@ static int tpa6130a2_power(u8 power)
|
||||||
}
|
}
|
||||||
|
|
||||||
data->power_state = 0;
|
data->power_state = 0;
|
||||||
|
/* device regs does not match the cache state anymore */
|
||||||
|
regcache_mark_dirty(data->regmap);
|
||||||
}
|
}
|
||||||
|
|
||||||
exit:
|
exit:
|
||||||
|
@ -196,7 +122,7 @@ static int tpa6130a2_get_volsw(struct snd_kcontrol *kcontrol,
|
||||||
struct tpa6130a2_data *data;
|
struct tpa6130a2_data *data;
|
||||||
unsigned int reg = mc->reg;
|
unsigned int reg = mc->reg;
|
||||||
unsigned int shift = mc->shift;
|
unsigned int shift = mc->shift;
|
||||||
int max = mc->max;
|
int max = mc->max, val;
|
||||||
unsigned int mask = (1 << fls(max)) - 1;
|
unsigned int mask = (1 << fls(max)) - 1;
|
||||||
unsigned int invert = mc->invert;
|
unsigned int invert = mc->invert;
|
||||||
|
|
||||||
|
@ -206,8 +132,8 @@ static int tpa6130a2_get_volsw(struct snd_kcontrol *kcontrol,
|
||||||
|
|
||||||
mutex_lock(&data->mutex);
|
mutex_lock(&data->mutex);
|
||||||
|
|
||||||
ucontrol->value.integer.value[0] =
|
regmap_read(data->regmap, reg, &val);
|
||||||
(tpa6130a2_read(reg) >> shift) & mask;
|
ucontrol->value.integer.value[0] = (val >> shift) & mask;
|
||||||
|
|
||||||
if (invert)
|
if (invert)
|
||||||
ucontrol->value.integer.value[0] =
|
ucontrol->value.integer.value[0] =
|
||||||
|
@ -229,7 +155,7 @@ static int tpa6130a2_put_volsw(struct snd_kcontrol *kcontrol,
|
||||||
unsigned int mask = (1 << fls(max)) - 1;
|
unsigned int mask = (1 << fls(max)) - 1;
|
||||||
unsigned int invert = mc->invert;
|
unsigned int invert = mc->invert;
|
||||||
unsigned int val = (ucontrol->value.integer.value[0] & mask);
|
unsigned int val = (ucontrol->value.integer.value[0] & mask);
|
||||||
unsigned int val_reg;
|
bool change;
|
||||||
|
|
||||||
if (WARN_ON(!tpa6130a2_client))
|
if (WARN_ON(!tpa6130a2_client))
|
||||||
return -EINVAL;
|
return -EINVAL;
|
||||||
|
@ -239,20 +165,11 @@ static int tpa6130a2_put_volsw(struct snd_kcontrol *kcontrol,
|
||||||
val = max - val;
|
val = max - val;
|
||||||
|
|
||||||
mutex_lock(&data->mutex);
|
mutex_lock(&data->mutex);
|
||||||
|
regmap_update_bits_check(data->regmap, reg, mask << shift, val << shift,
|
||||||
val_reg = tpa6130a2_read(reg);
|
&change);
|
||||||
if (((val_reg >> shift) & mask) == val) {
|
|
||||||
mutex_unlock(&data->mutex);
|
|
||||||
return 0;
|
|
||||||
}
|
|
||||||
|
|
||||||
val_reg &= ~(mask << shift);
|
|
||||||
val_reg |= val << shift;
|
|
||||||
tpa6130a2_i2c_write(reg, val_reg);
|
|
||||||
|
|
||||||
mutex_unlock(&data->mutex);
|
mutex_unlock(&data->mutex);
|
||||||
|
|
||||||
return 1;
|
return change;
|
||||||
}
|
}
|
||||||
|
|
||||||
/*
|
/*
|
||||||
|
@ -301,31 +218,26 @@ static const struct snd_kcontrol_new tpa6140a2_controls[] = {
|
||||||
*/
|
*/
|
||||||
static void tpa6130a2_channel_enable(u8 channel, int enable)
|
static void tpa6130a2_channel_enable(u8 channel, int enable)
|
||||||
{
|
{
|
||||||
u8 val;
|
struct tpa6130a2_data *data = i2c_get_clientdata(tpa6130a2_client);
|
||||||
|
|
||||||
if (enable) {
|
if (enable) {
|
||||||
/* Enable channel */
|
/* Enable channel */
|
||||||
/* Enable amplifier */
|
/* Enable amplifier */
|
||||||
val = tpa6130a2_read(TPA6130A2_REG_CONTROL);
|
regmap_update_bits(data->regmap, TPA6130A2_REG_CONTROL,
|
||||||
val |= channel;
|
channel | TPA6130A2_SWS, channel & ~TPA6130A2_SWS);
|
||||||
val &= ~TPA6130A2_SWS;
|
|
||||||
tpa6130a2_i2c_write(TPA6130A2_REG_CONTROL, val);
|
|
||||||
|
|
||||||
/* Unmute channel */
|
/* Unmute channel */
|
||||||
val = tpa6130a2_read(TPA6130A2_REG_VOL_MUTE);
|
regmap_update_bits(data->regmap, TPA6130A2_REG_VOL_MUTE,
|
||||||
val &= ~channel;
|
channel, 0);
|
||||||
tpa6130a2_i2c_write(TPA6130A2_REG_VOL_MUTE, val);
|
|
||||||
} else {
|
} else {
|
||||||
/* Disable channel */
|
/* Disable channel */
|
||||||
/* Mute channel */
|
/* Mute channel */
|
||||||
val = tpa6130a2_read(TPA6130A2_REG_VOL_MUTE);
|
regmap_update_bits(data->regmap, TPA6130A2_REG_VOL_MUTE,
|
||||||
val |= channel;
|
channel, channel);
|
||||||
tpa6130a2_i2c_write(TPA6130A2_REG_VOL_MUTE, val);
|
|
||||||
|
|
||||||
/* Disable amplifier */
|
/* Disable amplifier */
|
||||||
val = tpa6130a2_read(TPA6130A2_REG_CONTROL);
|
regmap_update_bits(data->regmap, TPA6130A2_REG_CONTROL,
|
||||||
val &= ~channel;
|
channel, 0);
|
||||||
tpa6130a2_i2c_write(TPA6130A2_REG_CONTROL, val);
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -365,6 +277,20 @@ struct snd_soc_component_driver tpa6130a2_component_driver = {
|
||||||
.probe = tpa6130a2_component_probe,
|
.probe = tpa6130a2_component_probe,
|
||||||
};
|
};
|
||||||
|
|
||||||
|
static const struct reg_default tpa6130a2_reg_defaults[] = {
|
||||||
|
{ TPA6130A2_REG_CONTROL, TPA6130A2_SWS },
|
||||||
|
{ TPA6130A2_REG_VOL_MUTE, TPA6130A2_MUTE_R | TPA6130A2_MUTE_L },
|
||||||
|
};
|
||||||
|
|
||||||
|
static const struct regmap_config tpa6130a2_regmap_config = {
|
||||||
|
.reg_bits = 8,
|
||||||
|
.val_bits = 8,
|
||||||
|
.max_register = TPA6130A2_REG_VERSION,
|
||||||
|
.reg_defaults = tpa6130a2_reg_defaults,
|
||||||
|
.num_reg_defaults = ARRAY_SIZE(tpa6130a2_reg_defaults),
|
||||||
|
.cache_type = REGCACHE_RBTREE,
|
||||||
|
};
|
||||||
|
|
||||||
static int tpa6130a2_probe(struct i2c_client *client,
|
static int tpa6130a2_probe(struct i2c_client *client,
|
||||||
const struct i2c_device_id *id)
|
const struct i2c_device_id *id)
|
||||||
{
|
{
|
||||||
|
@ -373,6 +299,7 @@ static int tpa6130a2_probe(struct i2c_client *client,
|
||||||
struct tpa6130a2_platform_data *pdata = client->dev.platform_data;
|
struct tpa6130a2_platform_data *pdata = client->dev.platform_data;
|
||||||
struct device_node *np = client->dev.of_node;
|
struct device_node *np = client->dev.of_node;
|
||||||
const char *regulator;
|
const char *regulator;
|
||||||
|
unsigned int version;
|
||||||
int ret;
|
int ret;
|
||||||
|
|
||||||
dev = &client->dev;
|
dev = &client->dev;
|
||||||
|
@ -381,6 +308,10 @@ static int tpa6130a2_probe(struct i2c_client *client,
|
||||||
if (!data)
|
if (!data)
|
||||||
return -ENOMEM;
|
return -ENOMEM;
|
||||||
|
|
||||||
|
data->regmap = devm_regmap_init_i2c(client, &tpa6130a2_regmap_config);
|
||||||
|
if (IS_ERR(data->regmap))
|
||||||
|
return PTR_ERR(data->regmap);
|
||||||
|
|
||||||
if (pdata) {
|
if (pdata) {
|
||||||
data->power_gpio = pdata->power_gpio;
|
data->power_gpio = pdata->power_gpio;
|
||||||
} else if (np) {
|
} else if (np) {
|
||||||
|
@ -399,11 +330,6 @@ static int tpa6130a2_probe(struct i2c_client *client,
|
||||||
|
|
||||||
mutex_init(&data->mutex);
|
mutex_init(&data->mutex);
|
||||||
|
|
||||||
/* Set default register values */
|
|
||||||
data->regs[TPA6130A2_REG_CONTROL] = TPA6130A2_SWS;
|
|
||||||
data->regs[TPA6130A2_REG_VOL_MUTE] = TPA6130A2_MUTE_R |
|
|
||||||
TPA6130A2_MUTE_L;
|
|
||||||
|
|
||||||
if (data->power_gpio >= 0) {
|
if (data->power_gpio >= 0) {
|
||||||
ret = devm_gpio_request(dev, data->power_gpio,
|
ret = devm_gpio_request(dev, data->power_gpio,
|
||||||
"tpa6130a2 enable");
|
"tpa6130a2 enable");
|
||||||
|
@ -440,10 +366,10 @@ static int tpa6130a2_probe(struct i2c_client *client,
|
||||||
|
|
||||||
|
|
||||||
/* Read version */
|
/* Read version */
|
||||||
ret = tpa6130a2_i2c_read(TPA6130A2_REG_VERSION) &
|
regmap_read(data->regmap, TPA6130A2_REG_VERSION, &version);
|
||||||
TPA6130A2_VERSION_MASK;
|
version &= TPA6130A2_VERSION_MASK;
|
||||||
if ((ret != 1) && (ret != 2))
|
if ((version != 1) && (version != 2))
|
||||||
dev_warn(dev, "UNTESTED version detected (%d)\n", ret);
|
dev_warn(dev, "UNTESTED version detected (%d)\n", version);
|
||||||
|
|
||||||
/* Disable the chip */
|
/* Disable the chip */
|
||||||
ret = tpa6130a2_power(0);
|
ret = tpa6130a2_power(0);
|
||||||
|
|
|
@ -30,8 +30,6 @@
|
||||||
#define TPA6130A2_REG_OUT_IMPEDANCE 0x03
|
#define TPA6130A2_REG_OUT_IMPEDANCE 0x03
|
||||||
#define TPA6130A2_REG_VERSION 0x04
|
#define TPA6130A2_REG_VERSION 0x04
|
||||||
|
|
||||||
#define TPA6130A2_CACHEREGNUM (TPA6130A2_REG_VERSION + 1)
|
|
||||||
|
|
||||||
/* Register bits */
|
/* Register bits */
|
||||||
/* TPA6130A2_REG_CONTROL (0x01) */
|
/* TPA6130A2_REG_CONTROL (0x01) */
|
||||||
#define TPA6130A2_SWS (0x01 << 0)
|
#define TPA6130A2_SWS (0x01 << 0)
|
||||||
|
|
Загрузка…
Ссылка в новой задаче