struct wm831x_pdata *pdata = wm831x->dev->platform_data;
int rev;
enum wm831x_parent parent;
- int ret;
+ int ret, i;
mutex_init(&wm831x->io_lock);
mutex_init(&wm831x->key_lock);
dev_err(wm831x->dev, "Failed to read parent ID: %d\n", ret);
goto err;
}
- if (ret != 0x6204) {
+ switch (ret) {
+ case 0x6204:
+ case 0x6246:
+ break;
+ default:
dev_err(wm831x->dev, "Device is not a WM831x: ID %x\n", ret);
ret = -EINVAL;
goto err;
dev_info(wm831x->dev, "WM8325 revision %c\n", 'A' + rev);
break;
+ case WM8326:
+ parent = WM8326;
+ wm831x->num_gpio = 12;
+ dev_info(wm831x->dev, "WM8326 revision %c\n", 'A' + rev);
+ break;
+
default:
dev_err(wm831x->dev, "Unknown WM831x device %04x\n", ret);
ret = -EINVAL;
}
}
+ if (pdata) {
+ for (i = 0; i < ARRAY_SIZE(pdata->gpio_defaults); i++) {
+ if (!pdata->gpio_defaults[i])
+ continue;
+
+ wm831x_reg_write(wm831x,
+ WM831X_GPIO1_CONTROL + i,
+ pdata->gpio_defaults[i] & 0xffff);
+ }
+ }
+
ret = wm831x_irq_init(wm831x, irq);
if (ret != 0)
goto err;
break;
case WM8320:
- ret = mfd_add_devices(wm831x->dev, -1,
- wm8320_devs, ARRAY_SIZE(wm8320_devs),
- NULL, 0);
- break;
-
case WM8321:
- ret = mfd_add_devices(wm831x->dev, -1,
- wm8320_devs, ARRAY_SIZE(wm8320_devs),
- NULL, 0);
- break;
-
case WM8325:
+ case WM8326:
ret = mfd_add_devices(wm831x->dev, -1,
wm8320_devs, ARRAY_SIZE(wm8320_devs),
- NULL, 0);
+ NULL, wm831x->irq_base);
break;
default:
return 0;
}
-static int wm831x_i2c_suspend(struct i2c_client *i2c, pm_message_t mesg)
+static int wm831x_i2c_suspend(struct device *dev)
{
- struct wm831x *wm831x = i2c_get_clientdata(i2c);
+ struct wm831x *wm831x = dev_get_drvdata(dev);
return wm831x_device_suspend(wm831x);
}
-static int wm831x_i2c_resume(struct i2c_client *i2c)
+static int wm831x_i2c_resume(struct device *dev)
{
- struct wm831x *wm831x = i2c_get_clientdata(i2c);
+ struct wm831x *wm831x = dev_get_drvdata(dev);
int i;
//set some intterupt again while resume
for (i = 0; i < ARRAY_SIZE(wm831x->irq_masks_cur); i++) {
{ "wm8320", WM8320 },
{ "wm8321", WM8321 },
{ "wm8325", WM8325 },
+ { "wm8326", WM8326 },
{ }
};
MODULE_DEVICE_TABLE(i2c, wm831x_i2c_id);
+static const struct dev_pm_ops wm831x_pm_ops = {
+ .suspend = wm831x_i2c_suspend,
+ .resume = wm831x_i2c_resume,
+};
static struct i2c_driver wm831x_i2c_driver = {
.driver = {
- .name = "wm831x",
- .owner = THIS_MODULE,
+ .name = "wm831x",
+ .owner = THIS_MODULE,
+ .pm = &wm831x_pm_ops,
},
.probe = wm831x_i2c_probe,
.remove = wm831x_i2c_remove,
- .suspend = wm831x_i2c_suspend,
- .resume = wm831x_i2c_resume,
.shutdown = wm831x_i2c_shutdown,
.id_table = wm831x_i2c_id,
};
static int __init wm831x_i2c_init(void)
{
int ret;
- printk("%s \n", __FUNCTION__);
+
+ printk("%s\n", __FUNCTION__);
ret = i2c_add_driver(&wm831x_i2c_driver);
if (ret != 0)
pr_err("Failed to register wm831x I2C driver: %d\n", ret);
return ret;
}
-//subsys_initcall(wm831x_i2c_init);
-//fs_initcall(wm831x_i2c_init);
subsys_initcall_sync(wm831x_i2c_init);
+
static void __exit wm831x_i2c_exit(void)
{
i2c_del_driver(&wm831x_i2c_driver);
#include <linux/kernel.h>
#include <linux/module.h>
+#include <linux/pm.h>
#include <linux/spi/spi.h>
#include <linux/gpio.h>
-
#include <linux/mfd/wm831x/core.h>
static int wm831x_spi_read_device(struct wm831x *wm831x, unsigned short reg,
type = WM8321;
else if (strcmp(spi->modalias, "wm8325") == 0)
type = WM8325;
+ else if (strcmp(spi->modalias, "wm8326") == 0)
+ type = WM8326;
else {
dev_err(&spi->dev, "Unknown device type\n");
return -EINVAL;
return 0;
}
-static int wm831x_spi_suspend(struct spi_device *spi, pm_message_t m)
+static int wm831x_spi_suspend(struct device *dev)
{
- struct wm831x *wm831x = dev_get_drvdata(&spi->dev);
+ struct wm831x *wm831x = dev_get_drvdata(dev);
+
spin_lock(&wm831x->flag_lock);
wm831x->flag_suspend = 1;
spin_unlock(&wm831x->flag_lock);
return wm831x_device_suspend(wm831x);
}
+static const struct dev_pm_ops wm831x_spi_pm = {
+ .freeze = wm831x_spi_suspend,
+ .suspend = wm831x_spi_suspend,
+};
+
static struct spi_driver wm8310_spi_driver = {
.driver = {
.name = "wm8310",
.bus = &spi_bus_type,
.owner = THIS_MODULE,
+ .pm = &wm831x_spi_pm,
},
.probe = wm831x_spi_probe,
.remove = __devexit_p(wm831x_spi_remove),
- .suspend = wm831x_spi_suspend,
};
static struct spi_driver wm8311_spi_driver = {
.name = "wm8311",
.bus = &spi_bus_type,
.owner = THIS_MODULE,
+ .pm = &wm831x_spi_pm,
},
.probe = wm831x_spi_probe,
.remove = __devexit_p(wm831x_spi_remove),
- .suspend = wm831x_spi_suspend,
};
static struct spi_driver wm8312_spi_driver = {
.name = "wm8312",
.bus = &spi_bus_type,
.owner = THIS_MODULE,
+ .pm = &wm831x_spi_pm,
},
.probe = wm831x_spi_probe,
.remove = __devexit_p(wm831x_spi_remove),
- .suspend = wm831x_spi_suspend,
};
static struct spi_driver wm8320_spi_driver = {
.name = "wm8320",
.bus = &spi_bus_type,
.owner = THIS_MODULE,
+ .pm = &wm831x_spi_pm,
},
.probe = wm831x_spi_probe,
.remove = __devexit_p(wm831x_spi_remove),
- .suspend = wm831x_spi_suspend,
};
static struct spi_driver wm8321_spi_driver = {
.name = "wm8321",
.bus = &spi_bus_type,
.owner = THIS_MODULE,
+ .pm = &wm831x_spi_pm,
},
.probe = wm831x_spi_probe,
.remove = __devexit_p(wm831x_spi_remove),
- .suspend = wm831x_spi_suspend,
};
static struct spi_driver wm8325_spi_driver = {
.name = "wm8325",
.bus = &spi_bus_type,
.owner = THIS_MODULE,
+ .pm = &wm831x_spi_pm,
+ },
+ .probe = wm831x_spi_probe,
+ .remove = __devexit_p(wm831x_spi_remove),
+};
+
+static struct spi_driver wm8326_spi_driver = {
+ .driver = {
+ .name = "wm8326",
+ .bus = &spi_bus_type,
+ .owner = THIS_MODULE,
+ .pm = &wm831x_spi_pm,
},
.probe = wm831x_spi_probe,
.remove = __devexit_p(wm831x_spi_remove),
- .suspend = wm831x_spi_suspend,
};
static int __init wm831x_spi_init(void)
if (ret != 0)
pr_err("Failed to register WM8325 SPI driver: %d\n", ret);
+ ret = spi_register_driver(&wm8326_spi_driver);
+ if (ret != 0)
+ pr_err("Failed to register WM8326 SPI driver: %d\n", ret);
+
return 0;
}
subsys_initcall(wm831x_spi_init);
static void __exit wm831x_spi_exit(void)
{
+ spi_unregister_driver(&wm8326_spi_driver);
spi_unregister_driver(&wm8325_spi_driver);
spi_unregister_driver(&wm8321_spi_driver);
spi_unregister_driver(&wm8320_spi_driver);
#define WM831X_NUM_IRQ_REGS 5
#define WM831X_IRQ_LIST 1
+
enum wm831x_parent {
WM8310 = 0x8310,
WM8311 = 0x8311,
WM8320 = 0x8320,
WM8321 = 0x8321,
WM8325 = 0x8325,
+ WM8326 = 0x8326,
};
struct wm831x {
int isel; /** Current for pen down (uA) */
int rpu; /** Pen down sensitivity resistor divider */
int pressure; /** Report pressure (boolean) */
- int data_irq; /** Touch data ready IRQ */
+ unsigned int data_irq; /** Touch data ready IRQ */
+ int data_irqf; /** IRQ flags for data ready IRQ */
+ unsigned int pd_irq; /** Touch pendown detect IRQ */
+ int pd_irqf; /** IRQ flags for pen down IRQ */
};
enum wm831x_watchdog_action {
#define WM831X_MAX_LDO 11
#define WM831X_MAX_ISINK 2
+#define WM831X_GPIO_CONFIGURE 0x10000
+#define WM831X_GPIO_NUM 16
+
struct wm831x_pdata {
+ /** Used to distinguish multiple WM831x chips */
+ int wm831x_num;
+
/** Called before subdevices are set up */
int (*pre_init)(struct wm831x *wm831x);
/** Called after subdevices are set up */
int settinginfolen;
int (*pin_type_init)(struct wm831x *wm831x);
//above add by sxj
+
+ /** Put the /IRQ line into CMOS mode */
+ bool irq_cmos;
+
int irq_base;
int gpio_base;
+ int gpio_defaults[WM831X_GPIO_NUM];
struct wm831x_backlight_pdata *backlight;
struct wm831x_backup_pdata *backup;
struct wm831x_battery_pdata *battery;