mfd: Convert WM8994 to use new register map API
Signed-off-by: Mark Brown <broonie@opensource.wolfsonmicro.com> Acked-by: Samuel Ortiz <sameo@linux.intel.com>
This commit is contained in:
@@ -490,6 +490,7 @@ config MFD_WM8350_I2C
|
|||||||
config MFD_WM8994
|
config MFD_WM8994
|
||||||
bool "Support Wolfson Microelectronics WM8994"
|
bool "Support Wolfson Microelectronics WM8994"
|
||||||
select MFD_CORE
|
select MFD_CORE
|
||||||
|
select REGMAP_I2C
|
||||||
depends on I2C=y && GENERIC_HARDIRQS
|
depends on I2C=y && GENERIC_HARDIRQS
|
||||||
help
|
help
|
||||||
The WM8994 is a highly integrated hi-fi CODEC designed for
|
The WM8994 is a highly integrated hi-fi CODEC designed for
|
||||||
|
@@ -16,9 +16,11 @@
|
|||||||
#include <linux/module.h>
|
#include <linux/module.h>
|
||||||
#include <linux/slab.h>
|
#include <linux/slab.h>
|
||||||
#include <linux/i2c.h>
|
#include <linux/i2c.h>
|
||||||
|
#include <linux/err.h>
|
||||||
#include <linux/delay.h>
|
#include <linux/delay.h>
|
||||||
#include <linux/mfd/core.h>
|
#include <linux/mfd/core.h>
|
||||||
#include <linux/pm_runtime.h>
|
#include <linux/pm_runtime.h>
|
||||||
|
#include <linux/regmap.h>
|
||||||
#include <linux/regulator/consumer.h>
|
#include <linux/regulator/consumer.h>
|
||||||
#include <linux/regulator/machine.h>
|
#include <linux/regulator/machine.h>
|
||||||
|
|
||||||
@@ -29,22 +31,7 @@
|
|||||||
static int wm8994_read(struct wm8994 *wm8994, unsigned short reg,
|
static int wm8994_read(struct wm8994 *wm8994, unsigned short reg,
|
||||||
int bytes, void *dest)
|
int bytes, void *dest)
|
||||||
{
|
{
|
||||||
int ret, i;
|
return regmap_raw_read(wm8994->regmap, reg, dest, bytes);
|
||||||
u16 *buf = dest;
|
|
||||||
|
|
||||||
BUG_ON(bytes % 2);
|
|
||||||
BUG_ON(bytes <= 0);
|
|
||||||
|
|
||||||
ret = wm8994->read_dev(wm8994, reg, bytes, dest);
|
|
||||||
if (ret < 0)
|
|
||||||
return ret;
|
|
||||||
|
|
||||||
for (i = 0; i < bytes / 2; i++) {
|
|
||||||
dev_vdbg(wm8994->dev, "Read %04x from R%d(0x%x)\n",
|
|
||||||
be16_to_cpu(buf[i]), reg + i, reg + i);
|
|
||||||
}
|
|
||||||
|
|
||||||
return 0;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
@@ -55,19 +42,15 @@ static int wm8994_read(struct wm8994 *wm8994, unsigned short reg,
|
|||||||
*/
|
*/
|
||||||
int wm8994_reg_read(struct wm8994 *wm8994, unsigned short reg)
|
int wm8994_reg_read(struct wm8994 *wm8994, unsigned short reg)
|
||||||
{
|
{
|
||||||
unsigned short val;
|
unsigned int val;
|
||||||
int ret;
|
int ret;
|
||||||
|
|
||||||
mutex_lock(&wm8994->io_lock);
|
ret = regmap_read(wm8994->regmap, reg, &val);
|
||||||
|
|
||||||
ret = wm8994_read(wm8994, reg, 2, &val);
|
|
||||||
|
|
||||||
mutex_unlock(&wm8994->io_lock);
|
|
||||||
|
|
||||||
if (ret < 0)
|
if (ret < 0)
|
||||||
return ret;
|
return ret;
|
||||||
else
|
else
|
||||||
return be16_to_cpu(val);
|
return val;
|
||||||
}
|
}
|
||||||
EXPORT_SYMBOL_GPL(wm8994_reg_read);
|
EXPORT_SYMBOL_GPL(wm8994_reg_read);
|
||||||
|
|
||||||
@@ -82,33 +65,13 @@ EXPORT_SYMBOL_GPL(wm8994_reg_read);
|
|||||||
int wm8994_bulk_read(struct wm8994 *wm8994, unsigned short reg,
|
int wm8994_bulk_read(struct wm8994 *wm8994, unsigned short reg,
|
||||||
int count, u16 *buf)
|
int count, u16 *buf)
|
||||||
{
|
{
|
||||||
int ret;
|
return regmap_bulk_read(wm8994->regmap, reg, buf, count);
|
||||||
|
|
||||||
mutex_lock(&wm8994->io_lock);
|
|
||||||
|
|
||||||
ret = wm8994_read(wm8994, reg, count * 2, buf);
|
|
||||||
|
|
||||||
mutex_unlock(&wm8994->io_lock);
|
|
||||||
|
|
||||||
return ret;
|
|
||||||
}
|
}
|
||||||
EXPORT_SYMBOL_GPL(wm8994_bulk_read);
|
|
||||||
|
|
||||||
static int wm8994_write(struct wm8994 *wm8994, unsigned short reg,
|
static int wm8994_write(struct wm8994 *wm8994, unsigned short reg,
|
||||||
int bytes, const void *src)
|
int bytes, const void *src)
|
||||||
{
|
{
|
||||||
const u16 *buf = src;
|
return regmap_raw_write(wm8994->regmap, reg, src, bytes);
|
||||||
int i;
|
|
||||||
|
|
||||||
BUG_ON(bytes % 2);
|
|
||||||
BUG_ON(bytes <= 0);
|
|
||||||
|
|
||||||
for (i = 0; i < bytes / 2; i++) {
|
|
||||||
dev_vdbg(wm8994->dev, "Write %04x to R%d(0x%x)\n",
|
|
||||||
be16_to_cpu(buf[i]), reg + i, reg + i);
|
|
||||||
}
|
|
||||||
|
|
||||||
return wm8994->write_dev(wm8994, reg, bytes, src);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
@@ -121,17 +84,7 @@ static int wm8994_write(struct wm8994 *wm8994, unsigned short reg,
|
|||||||
int wm8994_reg_write(struct wm8994 *wm8994, unsigned short reg,
|
int wm8994_reg_write(struct wm8994 *wm8994, unsigned short reg,
|
||||||
unsigned short val)
|
unsigned short val)
|
||||||
{
|
{
|
||||||
int ret;
|
return regmap_write(wm8994->regmap, reg, val);
|
||||||
|
|
||||||
val = cpu_to_be16(val);
|
|
||||||
|
|
||||||
mutex_lock(&wm8994->io_lock);
|
|
||||||
|
|
||||||
ret = wm8994_write(wm8994, reg, 2, &val);
|
|
||||||
|
|
||||||
mutex_unlock(&wm8994->io_lock);
|
|
||||||
|
|
||||||
return ret;
|
|
||||||
}
|
}
|
||||||
EXPORT_SYMBOL_GPL(wm8994_reg_write);
|
EXPORT_SYMBOL_GPL(wm8994_reg_write);
|
||||||
|
|
||||||
@@ -146,15 +99,7 @@ EXPORT_SYMBOL_GPL(wm8994_reg_write);
|
|||||||
int wm8994_bulk_write(struct wm8994 *wm8994, unsigned short reg,
|
int wm8994_bulk_write(struct wm8994 *wm8994, unsigned short reg,
|
||||||
int count, const u16 *buf)
|
int count, const u16 *buf)
|
||||||
{
|
{
|
||||||
int ret;
|
return regmap_raw_write(wm8994->regmap, reg, buf, count * sizeof(u16));
|
||||||
|
|
||||||
mutex_lock(&wm8994->io_lock);
|
|
||||||
|
|
||||||
ret = wm8994_write(wm8994, reg, count * 2, buf);
|
|
||||||
|
|
||||||
mutex_unlock(&wm8994->io_lock);
|
|
||||||
|
|
||||||
return ret;
|
|
||||||
}
|
}
|
||||||
EXPORT_SYMBOL_GPL(wm8994_bulk_write);
|
EXPORT_SYMBOL_GPL(wm8994_bulk_write);
|
||||||
|
|
||||||
@@ -169,28 +114,7 @@ EXPORT_SYMBOL_GPL(wm8994_bulk_write);
|
|||||||
int wm8994_set_bits(struct wm8994 *wm8994, unsigned short reg,
|
int wm8994_set_bits(struct wm8994 *wm8994, unsigned short reg,
|
||||||
unsigned short mask, unsigned short val)
|
unsigned short mask, unsigned short val)
|
||||||
{
|
{
|
||||||
int ret;
|
return regmap_update_bits(wm8994->regmap, reg, mask, val);
|
||||||
u16 r;
|
|
||||||
|
|
||||||
mutex_lock(&wm8994->io_lock);
|
|
||||||
|
|
||||||
ret = wm8994_read(wm8994, reg, 2, &r);
|
|
||||||
if (ret < 0)
|
|
||||||
goto out;
|
|
||||||
|
|
||||||
r = be16_to_cpu(r);
|
|
||||||
|
|
||||||
r &= ~mask;
|
|
||||||
r |= val;
|
|
||||||
|
|
||||||
r = cpu_to_be16(r);
|
|
||||||
|
|
||||||
ret = wm8994_write(wm8994, reg, 2, &r);
|
|
||||||
|
|
||||||
out:
|
|
||||||
mutex_unlock(&wm8994->io_lock);
|
|
||||||
|
|
||||||
return ret;
|
|
||||||
}
|
}
|
||||||
EXPORT_SYMBOL_GPL(wm8994_set_bits);
|
EXPORT_SYMBOL_GPL(wm8994_set_bits);
|
||||||
|
|
||||||
@@ -378,6 +302,11 @@ static int wm8994_ldo_in_use(struct wm8994_pdata *pdata, int ldo)
|
|||||||
}
|
}
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
|
static struct regmap_config wm8994_regmap_config = {
|
||||||
|
.reg_bits = 16,
|
||||||
|
.val_bits = 16,
|
||||||
|
};
|
||||||
|
|
||||||
/*
|
/*
|
||||||
* Instantiate the generic non-control parts of the device.
|
* Instantiate the generic non-control parts of the device.
|
||||||
*/
|
*/
|
||||||
@@ -387,7 +316,6 @@ static int wm8994_device_init(struct wm8994 *wm8994, int irq)
|
|||||||
const char *devname;
|
const char *devname;
|
||||||
int ret, i;
|
int ret, i;
|
||||||
|
|
||||||
mutex_init(&wm8994->io_lock);
|
|
||||||
dev_set_drvdata(wm8994->dev, wm8994);
|
dev_set_drvdata(wm8994->dev, wm8994);
|
||||||
|
|
||||||
/* Add the on-chip regulators first for bootstrapping */
|
/* Add the on-chip regulators first for bootstrapping */
|
||||||
@@ -397,7 +325,7 @@ static int wm8994_device_init(struct wm8994 *wm8994, int irq)
|
|||||||
NULL, 0);
|
NULL, 0);
|
||||||
if (ret != 0) {
|
if (ret != 0) {
|
||||||
dev_err(wm8994->dev, "Failed to add children: %d\n", ret);
|
dev_err(wm8994->dev, "Failed to add children: %d\n", ret);
|
||||||
goto err;
|
goto err_regmap;
|
||||||
}
|
}
|
||||||
|
|
||||||
switch (wm8994->type) {
|
switch (wm8994->type) {
|
||||||
@@ -409,7 +337,7 @@ static int wm8994_device_init(struct wm8994 *wm8994, int irq)
|
|||||||
break;
|
break;
|
||||||
default:
|
default:
|
||||||
BUG();
|
BUG();
|
||||||
goto err;
|
goto err_regmap;
|
||||||
}
|
}
|
||||||
|
|
||||||
wm8994->supplies = kzalloc(sizeof(struct regulator_bulk_data) *
|
wm8994->supplies = kzalloc(sizeof(struct regulator_bulk_data) *
|
||||||
@@ -417,7 +345,7 @@ static int wm8994_device_init(struct wm8994 *wm8994, int irq)
|
|||||||
GFP_KERNEL);
|
GFP_KERNEL);
|
||||||
if (!wm8994->supplies) {
|
if (!wm8994->supplies) {
|
||||||
ret = -ENOMEM;
|
ret = -ENOMEM;
|
||||||
goto err;
|
goto err_regmap;
|
||||||
}
|
}
|
||||||
|
|
||||||
switch (wm8994->type) {
|
switch (wm8994->type) {
|
||||||
@@ -431,7 +359,7 @@ static int wm8994_device_init(struct wm8994 *wm8994, int irq)
|
|||||||
break;
|
break;
|
||||||
default:
|
default:
|
||||||
BUG();
|
BUG();
|
||||||
goto err;
|
goto err_regmap;
|
||||||
}
|
}
|
||||||
|
|
||||||
ret = regulator_bulk_get(wm8994->dev, wm8994->num_supplies,
|
ret = regulator_bulk_get(wm8994->dev, wm8994->num_supplies,
|
||||||
@@ -554,7 +482,8 @@ err_get:
|
|||||||
regulator_bulk_free(wm8994->num_supplies, wm8994->supplies);
|
regulator_bulk_free(wm8994->num_supplies, wm8994->supplies);
|
||||||
err_supplies:
|
err_supplies:
|
||||||
kfree(wm8994->supplies);
|
kfree(wm8994->supplies);
|
||||||
err:
|
err_regmap:
|
||||||
|
regmap_exit(wm8994->regmap);
|
||||||
mfd_remove_devices(wm8994->dev);
|
mfd_remove_devices(wm8994->dev);
|
||||||
kfree(wm8994);
|
kfree(wm8994);
|
||||||
return ret;
|
return ret;
|
||||||
@@ -569,62 +498,15 @@ static void wm8994_device_exit(struct wm8994 *wm8994)
|
|||||||
wm8994->supplies);
|
wm8994->supplies);
|
||||||
regulator_bulk_free(wm8994->num_supplies, wm8994->supplies);
|
regulator_bulk_free(wm8994->num_supplies, wm8994->supplies);
|
||||||
kfree(wm8994->supplies);
|
kfree(wm8994->supplies);
|
||||||
|
regmap_exit(wm8994->regmap);
|
||||||
kfree(wm8994);
|
kfree(wm8994);
|
||||||
}
|
}
|
||||||
|
|
||||||
static int wm8994_i2c_read_device(struct wm8994 *wm8994, unsigned short reg,
|
|
||||||
int bytes, void *dest)
|
|
||||||
{
|
|
||||||
struct i2c_client *i2c = wm8994->control_data;
|
|
||||||
int ret;
|
|
||||||
u16 r = cpu_to_be16(reg);
|
|
||||||
|
|
||||||
ret = i2c_master_send(i2c, (unsigned char *)&r, 2);
|
|
||||||
if (ret < 0)
|
|
||||||
return ret;
|
|
||||||
if (ret != 2)
|
|
||||||
return -EIO;
|
|
||||||
|
|
||||||
ret = i2c_master_recv(i2c, dest, bytes);
|
|
||||||
if (ret < 0)
|
|
||||||
return ret;
|
|
||||||
if (ret != bytes)
|
|
||||||
return -EIO;
|
|
||||||
return 0;
|
|
||||||
}
|
|
||||||
|
|
||||||
static int wm8994_i2c_write_device(struct wm8994 *wm8994, unsigned short reg,
|
|
||||||
int bytes, const void *src)
|
|
||||||
{
|
|
||||||
struct i2c_client *i2c = wm8994->control_data;
|
|
||||||
struct i2c_msg xfer[2];
|
|
||||||
int ret;
|
|
||||||
|
|
||||||
reg = cpu_to_be16(reg);
|
|
||||||
|
|
||||||
xfer[0].addr = i2c->addr;
|
|
||||||
xfer[0].flags = 0;
|
|
||||||
xfer[0].len = 2;
|
|
||||||
xfer[0].buf = (char *)®
|
|
||||||
|
|
||||||
xfer[1].addr = i2c->addr;
|
|
||||||
xfer[1].flags = I2C_M_NOSTART;
|
|
||||||
xfer[1].len = bytes;
|
|
||||||
xfer[1].buf = (char *)src;
|
|
||||||
|
|
||||||
ret = i2c_transfer(i2c->adapter, xfer, 2);
|
|
||||||
if (ret < 0)
|
|
||||||
return ret;
|
|
||||||
if (ret != 2)
|
|
||||||
return -EIO;
|
|
||||||
|
|
||||||
return 0;
|
|
||||||
}
|
|
||||||
|
|
||||||
static int wm8994_i2c_probe(struct i2c_client *i2c,
|
static int wm8994_i2c_probe(struct i2c_client *i2c,
|
||||||
const struct i2c_device_id *id)
|
const struct i2c_device_id *id)
|
||||||
{
|
{
|
||||||
struct wm8994 *wm8994;
|
struct wm8994 *wm8994;
|
||||||
|
int ret;
|
||||||
|
|
||||||
wm8994 = kzalloc(sizeof(struct wm8994), GFP_KERNEL);
|
wm8994 = kzalloc(sizeof(struct wm8994), GFP_KERNEL);
|
||||||
if (wm8994 == NULL)
|
if (wm8994 == NULL)
|
||||||
@@ -632,12 +514,18 @@ static int wm8994_i2c_probe(struct i2c_client *i2c,
|
|||||||
|
|
||||||
i2c_set_clientdata(i2c, wm8994);
|
i2c_set_clientdata(i2c, wm8994);
|
||||||
wm8994->dev = &i2c->dev;
|
wm8994->dev = &i2c->dev;
|
||||||
wm8994->control_data = i2c;
|
|
||||||
wm8994->read_dev = wm8994_i2c_read_device;
|
|
||||||
wm8994->write_dev = wm8994_i2c_write_device;
|
|
||||||
wm8994->irq = i2c->irq;
|
wm8994->irq = i2c->irq;
|
||||||
wm8994->type = id->driver_data;
|
wm8994->type = id->driver_data;
|
||||||
|
|
||||||
|
wm8994->regmap = regmap_init_i2c(i2c, &wm8994_regmap_config);
|
||||||
|
if (IS_ERR(wm8994->regmap)) {
|
||||||
|
ret = PTR_ERR(wm8994->regmap);
|
||||||
|
dev_err(wm8994->dev, "Failed to allocate register map: %d\n",
|
||||||
|
ret);
|
||||||
|
kfree(wm8994);
|
||||||
|
return ret;
|
||||||
|
}
|
||||||
|
|
||||||
return wm8994_device_init(wm8994, i2c->irq);
|
return wm8994_device_init(wm8994, i2c->irq);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@@ -24,6 +24,7 @@ enum wm8994_type {
|
|||||||
|
|
||||||
struct regulator_dev;
|
struct regulator_dev;
|
||||||
struct regulator_bulk_data;
|
struct regulator_bulk_data;
|
||||||
|
struct regmap;
|
||||||
|
|
||||||
#define WM8994_NUM_GPIO_REGS 11
|
#define WM8994_NUM_GPIO_REGS 11
|
||||||
#define WM8994_NUM_LDO_REGS 2
|
#define WM8994_NUM_LDO_REGS 2
|
||||||
@@ -50,18 +51,12 @@ struct regulator_bulk_data;
|
|||||||
#define WM8994_IRQ_GPIO(x) (x + WM8994_IRQ_TEMP_WARN)
|
#define WM8994_IRQ_GPIO(x) (x + WM8994_IRQ_TEMP_WARN)
|
||||||
|
|
||||||
struct wm8994 {
|
struct wm8994 {
|
||||||
struct mutex io_lock;
|
|
||||||
struct mutex irq_lock;
|
struct mutex irq_lock;
|
||||||
|
|
||||||
enum wm8994_type type;
|
enum wm8994_type type;
|
||||||
|
|
||||||
struct device *dev;
|
struct device *dev;
|
||||||
int (*read_dev)(struct wm8994 *wm8994, unsigned short reg,
|
struct regmap *regmap;
|
||||||
int bytes, void *dest);
|
|
||||||
int (*write_dev)(struct wm8994 *wm8994, unsigned short reg,
|
|
||||||
int bytes, const void *src);
|
|
||||||
|
|
||||||
void *control_data;
|
|
||||||
|
|
||||||
int gpio_base;
|
int gpio_base;
|
||||||
int irq_base;
|
int irq_base;
|
||||||
|
Reference in New Issue
Block a user