Commit d6c645fc authored by Mark Brown's avatar Mark Brown

mfd: Convert WM8994 to use new register map API

Signed-off-by: default avatarMark Brown <broonie@opensource.wolfsonmicro.com>
Acked-by: default avatarSamuel Ortiz <sameo@linux.intel.com>
parent 5570c2f7
...@@ -490,6 +490,7 @@ config MFD_WM8350_I2C ...@@ -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 @@ ...@@ -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 @@ ...@@ -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, ...@@ -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); ...@@ -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, ...@@ -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); ...@@ -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); ...@@ -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) ...@@ -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) ...@@ -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) ...@@ -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) ...@@ -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) ...@@ -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) ...@@ -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 @@ static int wm8994_device_init(struct wm8994 *wm8994, int irq) ...@@ -554,7 +482,8 @@ static int wm8994_device_init(struct wm8994 *wm8994, int irq)
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) ...@@ -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 *)&reg;
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, ...@@ -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 { ...@@ -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; ...@@ -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;
......
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