summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
-rw-r--r--drivers/mfd/Kconfig10
-rw-r--r--drivers/mfd/Makefile1
-rw-r--r--drivers/mfd/aat2870-core.c535
-rw-r--r--include/linux/mfd/aat2870.h181
4 files changed, 727 insertions, 0 deletions
diff --git a/drivers/mfd/Kconfig b/drivers/mfd/Kconfig
index c26136443c05..21574bdf485f 100644
--- a/drivers/mfd/Kconfig
+++ b/drivers/mfd/Kconfig
@@ -760,6 +760,16 @@ config MFD_PM8XXX_IRQ
760config TPS65911_COMPARATOR 760config TPS65911_COMPARATOR
761 tristate 761 tristate
762 762
763config MFD_AAT2870_CORE
764 bool "Support for the AnalogicTech AAT2870"
765 select MFD_CORE
766 depends on I2C=y && GPIOLIB
767 help
768 If you say yes here you get support for the AAT2870.
769 This driver provides common support for accessing the device,
770 additional drivers must be enabled in order to use the
771 functionality of the device.
772
763endif # MFD_SUPPORT 773endif # MFD_SUPPORT
764 774
765menu "Multimedia Capabilities Port drivers" 775menu "Multimedia Capabilities Port drivers"
diff --git a/drivers/mfd/Makefile b/drivers/mfd/Makefile
index ca1867db3db8..c58020303d18 100644
--- a/drivers/mfd/Makefile
+++ b/drivers/mfd/Makefile
@@ -101,3 +101,4 @@ obj-$(CONFIG_MFD_OMAP_USB_HOST) += omap-usb-host.o
101obj-$(CONFIG_MFD_PM8921_CORE) += pm8921-core.o 101obj-$(CONFIG_MFD_PM8921_CORE) += pm8921-core.o
102obj-$(CONFIG_MFD_PM8XXX_IRQ) += pm8xxx-irq.o 102obj-$(CONFIG_MFD_PM8XXX_IRQ) += pm8xxx-irq.o
103obj-$(CONFIG_TPS65911_COMPARATOR) += tps65911-comparator.o 103obj-$(CONFIG_TPS65911_COMPARATOR) += tps65911-comparator.o
104obj-$(CONFIG_MFD_AAT2870_CORE) += aat2870-core.o
diff --git a/drivers/mfd/aat2870-core.c b/drivers/mfd/aat2870-core.c
new file mode 100644
index 000000000000..345dc658ef06
--- /dev/null
+++ b/drivers/mfd/aat2870-core.c
@@ -0,0 +1,535 @@
1/*
2 * linux/drivers/mfd/aat2870-core.c
3 *
4 * Copyright (c) 2011, NVIDIA Corporation.
5 * Author: Jin Park <jinyoungp@nvidia.com>
6 *
7 * This program is free software; you can redistribute it and/or
8 * modify it under the terms of the GNU General Public License
9 * version 2 as published by the Free Software Foundation.
10 *
11 * This program is distributed in the hope that it will be useful, but
12 * WITHOUT ANY WARRANTY; without even the implied warranty of
13 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
14 * General Public License for more details.
15 *
16 * You should have received a copy of the GNU General Public License
17 * along with this program; if not, write to the Free Software
18 * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA
19 * 02110-1301 USA
20 */
21
22#include <linux/kernel.h>
23#include <linux/module.h>
24#include <linux/init.h>
25#include <linux/debugfs.h>
26#include <linux/slab.h>
27#include <linux/uaccess.h>
28#include <linux/i2c.h>
29#include <linux/delay.h>
30#include <linux/gpio.h>
31#include <linux/mfd/core.h>
32#include <linux/mfd/aat2870.h>
33#include <linux/regulator/machine.h>
34
35static struct aat2870_register aat2870_regs[AAT2870_REG_NUM] = {
36 /* readable, writeable, value */
37 { 0, 1, 0x00 }, /* 0x00 AAT2870_BL_CH_EN */
38 { 0, 1, 0x16 }, /* 0x01 AAT2870_BLM */
39 { 0, 1, 0x16 }, /* 0x02 AAT2870_BLS */
40 { 0, 1, 0x56 }, /* 0x03 AAT2870_BL1 */
41 { 0, 1, 0x56 }, /* 0x04 AAT2870_BL2 */
42 { 0, 1, 0x56 }, /* 0x05 AAT2870_BL3 */
43 { 0, 1, 0x56 }, /* 0x06 AAT2870_BL4 */
44 { 0, 1, 0x56 }, /* 0x07 AAT2870_BL5 */
45 { 0, 1, 0x56 }, /* 0x08 AAT2870_BL6 */
46 { 0, 1, 0x56 }, /* 0x09 AAT2870_BL7 */
47 { 0, 1, 0x56 }, /* 0x0A AAT2870_BL8 */
48 { 0, 1, 0x00 }, /* 0x0B AAT2870_FLR */
49 { 0, 1, 0x03 }, /* 0x0C AAT2870_FM */
50 { 0, 1, 0x03 }, /* 0x0D AAT2870_FS */
51 { 0, 1, 0x10 }, /* 0x0E AAT2870_ALS_CFG0 */
52 { 0, 1, 0x06 }, /* 0x0F AAT2870_ALS_CFG1 */
53 { 0, 1, 0x00 }, /* 0x10 AAT2870_ALS_CFG2 */
54 { 1, 0, 0x00 }, /* 0x11 AAT2870_AMB */
55 { 0, 1, 0x00 }, /* 0x12 AAT2870_ALS0 */
56 { 0, 1, 0x00 }, /* 0x13 AAT2870_ALS1 */
57 { 0, 1, 0x00 }, /* 0x14 AAT2870_ALS2 */
58 { 0, 1, 0x00 }, /* 0x15 AAT2870_ALS3 */
59 { 0, 1, 0x00 }, /* 0x16 AAT2870_ALS4 */
60 { 0, 1, 0x00 }, /* 0x17 AAT2870_ALS5 */
61 { 0, 1, 0x00 }, /* 0x18 AAT2870_ALS6 */
62 { 0, 1, 0x00 }, /* 0x19 AAT2870_ALS7 */
63 { 0, 1, 0x00 }, /* 0x1A AAT2870_ALS8 */
64 { 0, 1, 0x00 }, /* 0x1B AAT2870_ALS9 */
65 { 0, 1, 0x00 }, /* 0x1C AAT2870_ALSA */
66 { 0, 1, 0x00 }, /* 0x1D AAT2870_ALSB */
67 { 0, 1, 0x00 }, /* 0x1E AAT2870_ALSC */
68 { 0, 1, 0x00 }, /* 0x1F AAT2870_ALSD */
69 { 0, 1, 0x00 }, /* 0x20 AAT2870_ALSE */
70 { 0, 1, 0x00 }, /* 0x21 AAT2870_ALSF */
71 { 0, 1, 0x00 }, /* 0x22 AAT2870_SUB_SET */
72 { 0, 1, 0x00 }, /* 0x23 AAT2870_SUB_CTRL */
73 { 0, 1, 0x00 }, /* 0x24 AAT2870_LDO_AB */
74 { 0, 1, 0x00 }, /* 0x25 AAT2870_LDO_CD */
75 { 0, 1, 0x00 }, /* 0x26 AAT2870_LDO_EN */
76};
77
78static struct mfd_cell aat2870_devs[] = {
79 {
80 .name = "aat2870-backlight",
81 .id = AAT2870_ID_BL,
82 .pdata_size = sizeof(struct aat2870_bl_platform_data),
83 },
84 {
85 .name = "aat2870-regulator",
86 .id = AAT2870_ID_LDOA,
87 .pdata_size = sizeof(struct regulator_init_data),
88 },
89 {
90 .name = "aat2870-regulator",
91 .id = AAT2870_ID_LDOB,
92 .pdata_size = sizeof(struct regulator_init_data),
93 },
94 {
95 .name = "aat2870-regulator",
96 .id = AAT2870_ID_LDOC,
97 .pdata_size = sizeof(struct regulator_init_data),
98 },
99 {
100 .name = "aat2870-regulator",
101 .id = AAT2870_ID_LDOD,
102 .pdata_size = sizeof(struct regulator_init_data),
103 },
104};
105
106static int __aat2870_read(struct aat2870_data *aat2870, u8 addr, u8 *val)
107{
108 int ret;
109
110 if (addr >= AAT2870_REG_NUM) {
111 dev_err(aat2870->dev, "Invalid address, 0x%02x\n", addr);
112 return -EINVAL;
113 }
114
115 if (!aat2870->reg_cache[addr].readable) {
116 *val = aat2870->reg_cache[addr].value;
117 goto out;
118 }
119
120 ret = i2c_master_send(aat2870->client, &addr, 1);
121 if (ret < 0)
122 return ret;
123 if (ret != 1)
124 return -EIO;
125
126 ret = i2c_master_recv(aat2870->client, val, 1);
127 if (ret < 0)
128 return ret;
129 if (ret != 1)
130 return -EIO;
131
132out:
133 dev_dbg(aat2870->dev, "read: addr=0x%02x, val=0x%02x\n", addr, *val);
134 return 0;
135}
136
137static int __aat2870_write(struct aat2870_data *aat2870, u8 addr, u8 val)
138{
139 u8 msg[2];
140 int ret;
141
142 if (addr >= AAT2870_REG_NUM) {
143 dev_err(aat2870->dev, "Invalid address, 0x%02x\n", addr);
144 return -EINVAL;
145 }
146
147 if (!aat2870->reg_cache[addr].writeable) {
148 dev_err(aat2870->dev, "Address 0x%02x is not writeable\n",
149 addr);
150 return -EINVAL;
151 }
152
153 msg[0] = addr;
154 msg[1] = val;
155 ret = i2c_master_send(aat2870->client, msg, 2);
156 if (ret < 0)
157 return ret;
158 if (ret != 2)
159 return -EIO;
160
161 aat2870->reg_cache[addr].value = val;
162
163 dev_dbg(aat2870->dev, "write: addr=0x%02x, val=0x%02x\n", addr, val);
164 return 0;
165}
166
167static int aat2870_read(struct aat2870_data *aat2870, u8 addr, u8 *val)
168{
169 int ret;
170
171 mutex_lock(&aat2870->io_lock);
172 ret = __aat2870_read(aat2870, addr, val);
173 mutex_unlock(&aat2870->io_lock);
174
175 return ret;
176}
177
178static int aat2870_write(struct aat2870_data *aat2870, u8 addr, u8 val)
179{
180 int ret;
181
182 mutex_lock(&aat2870->io_lock);
183 ret = __aat2870_write(aat2870, addr, val);
184 mutex_unlock(&aat2870->io_lock);
185
186 return ret;
187}
188
189static int aat2870_update(struct aat2870_data *aat2870, u8 addr, u8 mask,
190 u8 val)
191{
192 int change;
193 u8 old_val, new_val;
194 int ret;
195
196 mutex_lock(&aat2870->io_lock);
197
198 ret = __aat2870_read(aat2870, addr, &old_val);
199 if (ret)
200 goto out_unlock;
201
202 new_val = (old_val & ~mask) | (val & mask);
203 change = old_val != new_val;
204 if (change)
205 ret = __aat2870_write(aat2870, addr, new_val);
206
207out_unlock:
208 mutex_unlock(&aat2870->io_lock);
209
210 return ret;
211}
212
213static inline void aat2870_enable(struct aat2870_data *aat2870)
214{
215 if (aat2870->en_pin >= 0)
216 gpio_set_value(aat2870->en_pin, 1);
217
218 aat2870->is_enable = 1;
219}
220
221static inline void aat2870_disable(struct aat2870_data *aat2870)
222{
223 if (aat2870->en_pin >= 0)
224 gpio_set_value(aat2870->en_pin, 0);
225
226 aat2870->is_enable = 0;
227}
228
229#ifdef CONFIG_DEBUG_FS
230static ssize_t aat2870_dump_reg(struct aat2870_data *aat2870, char *buf)
231{
232 u8 addr, val;
233 ssize_t count = 0;
234 int ret;
235
236 count += sprintf(buf, "aat2870 registers\n");
237 for (addr = 0; addr < AAT2870_REG_NUM; addr++) {
238 count += sprintf(buf + count, "0x%02x: ", addr);
239 if (count >= PAGE_SIZE - 1)
240 break;
241
242 ret = aat2870->read(aat2870, addr, &val);
243 if (ret == 0)
244 count += snprintf(buf + count, PAGE_SIZE - count,
245 "0x%02x", val);
246 else
247 count += snprintf(buf + count, PAGE_SIZE - count,
248 "<read fail: %d>", ret);
249
250 if (count >= PAGE_SIZE - 1)
251 break;
252
253 count += snprintf(buf + count, PAGE_SIZE - count, "\n");
254 if (count >= PAGE_SIZE - 1)
255 break;
256 }
257
258 /* Truncate count; min() would cause a warning */
259 if (count >= PAGE_SIZE)
260 count = PAGE_SIZE - 1;
261
262 return count;
263}
264
265static int aat2870_reg_open_file(struct inode *inode, struct file *file)
266{
267 file->private_data = inode->i_private;
268
269 return 0;
270}
271
272static ssize_t aat2870_reg_read_file(struct file *file, char __user *user_buf,
273 size_t count, loff_t *ppos)
274{
275 struct aat2870_data *aat2870 = file->private_data;
276 char *buf;
277 ssize_t ret;
278
279 buf = kmalloc(PAGE_SIZE, GFP_KERNEL);
280 if (!buf)
281 return -ENOMEM;
282
283 ret = aat2870_dump_reg(aat2870, buf);
284 if (ret >= 0)
285 ret = simple_read_from_buffer(user_buf, count, ppos, buf, ret);
286
287 kfree(buf);
288
289 return ret;
290}
291
292static ssize_t aat2870_reg_write_file(struct file *file,
293 const char __user *user_buf, size_t count,
294 loff_t *ppos)
295{
296 struct aat2870_data *aat2870 = file->private_data;
297 char buf[32];
298 int buf_size;
299 char *start = buf;
300 unsigned long addr, val;
301 int ret;
302
303 buf_size = min(count, (sizeof(buf)-1));
304 if (copy_from_user(buf, user_buf, buf_size)) {
305 dev_err(aat2870->dev, "Failed to copy from user\n");
306 return -EFAULT;
307 }
308 buf[buf_size] = 0;
309
310 while (*start == ' ')
311 start++;
312
313 addr = simple_strtoul(start, &start, 16);
314 if (addr >= AAT2870_REG_NUM) {
315 dev_err(aat2870->dev, "Invalid address, 0x%lx\n", addr);
316 return -EINVAL;
317 }
318
319 while (*start == ' ')
320 start++;
321
322 if (strict_strtoul(start, 16, &val))
323 return -EINVAL;
324
325 ret = aat2870->write(aat2870, (u8)addr, (u8)val);
326 if (ret)
327 return ret;
328
329 return buf_size;
330}
331
332static const struct file_operations aat2870_reg_fops = {
333 .open = aat2870_reg_open_file,
334 .read = aat2870_reg_read_file,
335 .write = aat2870_reg_write_file,
336};
337
338static void aat2870_init_debugfs(struct aat2870_data *aat2870)
339{
340 aat2870->dentry_root = debugfs_create_dir("aat2870", NULL);
341 if (!aat2870->dentry_root) {
342 dev_warn(aat2870->dev,
343 "Failed to create debugfs root directory\n");
344 return;
345 }
346
347 aat2870->dentry_reg = debugfs_create_file("regs", 0644,
348 aat2870->dentry_root,
349 aat2870, &aat2870_reg_fops);
350 if (!aat2870->dentry_reg)
351 dev_warn(aat2870->dev,
352 "Failed to create debugfs register file\n");
353}
354
355static void aat2870_uninit_debugfs(struct aat2870_data *aat2870)
356{
357 debugfs_remove_recursive(aat2870->dentry_root);
358}
359#else
360static inline void aat2870_init_debugfs(struct aat2870_data *aat2870)
361{
362}
363
364static inline void aat2870_uninit_debugfs(struct aat2870_data *aat2870)
365{
366}
367#endif /* CONFIG_DEBUG_FS */
368
369static int aat2870_i2c_probe(struct i2c_client *client,
370 const struct i2c_device_id *id)
371{
372 struct aat2870_platform_data *pdata = client->dev.platform_data;
373 struct aat2870_data *aat2870;
374 int i, j;
375 int ret = 0;
376
377 aat2870 = kzalloc(sizeof(struct aat2870_data), GFP_KERNEL);
378 if (!aat2870) {
379 dev_err(&client->dev,
380 "Failed to allocate memory for aat2870\n");
381 ret = -ENOMEM;
382 goto out;
383 }
384
385 aat2870->dev = &client->dev;
386 dev_set_drvdata(aat2870->dev, aat2870);
387
388 aat2870->client = client;
389 i2c_set_clientdata(client, aat2870);
390
391 aat2870->reg_cache = aat2870_regs;
392
393 if (pdata->en_pin < 0)
394 aat2870->en_pin = -1;
395 else
396 aat2870->en_pin = pdata->en_pin;
397
398 aat2870->init = pdata->init;
399 aat2870->uninit = pdata->uninit;
400 aat2870->read = aat2870_read;
401 aat2870->write = aat2870_write;
402 aat2870->update = aat2870_update;
403
404 mutex_init(&aat2870->io_lock);
405
406 if (aat2870->init)
407 aat2870->init(aat2870);
408
409 if (aat2870->en_pin >= 0) {
410 ret = gpio_request(aat2870->en_pin, "aat2870-en");
411 if (ret < 0) {
412 dev_err(&client->dev,
413 "Failed to request GPIO %d\n", aat2870->en_pin);
414 goto out_kfree;
415 }
416 gpio_direction_output(aat2870->en_pin, 1);
417 }
418
419 aat2870_enable(aat2870);
420
421 for (i = 0; i < pdata->num_subdevs; i++) {
422 for (j = 0; j < ARRAY_SIZE(aat2870_devs); j++) {
423 if ((pdata->subdevs[i].id == aat2870_devs[j].id) &&
424 !strcmp(pdata->subdevs[i].name,
425 aat2870_devs[j].name)) {
426 aat2870_devs[j].platform_data =
427 pdata->subdevs[i].platform_data;
428 break;
429 }
430 }
431 }
432
433 ret = mfd_add_devices(aat2870->dev, 0, aat2870_devs,
434 ARRAY_SIZE(aat2870_devs), NULL, 0);
435 if (ret != 0) {
436 dev_err(aat2870->dev, "Failed to add subdev: %d\n", ret);
437 goto out_disable;
438 }
439
440 aat2870_init_debugfs(aat2870);
441
442 return 0;
443
444out_disable:
445 aat2870_disable(aat2870);
446 if (aat2870->en_pin >= 0)
447 gpio_free(aat2870->en_pin);
448out_kfree:
449 kfree(aat2870);
450out:
451 return ret;
452}
453
454static int aat2870_i2c_remove(struct i2c_client *client)
455{
456 struct aat2870_data *aat2870 = i2c_get_clientdata(client);
457
458 aat2870_uninit_debugfs(aat2870);
459
460 mfd_remove_devices(aat2870->dev);
461 aat2870_disable(aat2870);
462 if (aat2870->en_pin >= 0)
463 gpio_free(aat2870->en_pin);
464 if (aat2870->uninit)
465 aat2870->uninit(aat2870);
466 kfree(aat2870);
467
468 return 0;
469}
470
471#ifdef CONFIG_PM
472static int aat2870_i2c_suspend(struct i2c_client *client, pm_message_t state)
473{
474 struct aat2870_data *aat2870 = i2c_get_clientdata(client);
475
476 aat2870_disable(aat2870);
477
478 return 0;
479}
480
481static int aat2870_i2c_resume(struct i2c_client *client)
482{
483 struct aat2870_data *aat2870 = i2c_get_clientdata(client);
484 struct aat2870_register *reg = NULL;
485 int i;
486
487 aat2870_enable(aat2870);
488
489 /* restore registers */
490 for (i = 0; i < AAT2870_REG_NUM; i++) {
491 reg = &aat2870->reg_cache[i];
492 if (reg->writeable)
493 aat2870->write(aat2870, i, reg->value);
494 }
495
496 return 0;
497}
498#else
499#define aat2870_i2c_suspend NULL
500#define aat2870_i2c_resume NULL
501#endif /* CONFIG_PM */
502
503static struct i2c_device_id aat2870_i2c_id_table[] = {
504 { "aat2870", 0 },
505 { }
506};
507MODULE_DEVICE_TABLE(i2c, aat2870_i2c_id_table);
508
509static struct i2c_driver aat2870_i2c_driver = {
510 .driver = {
511 .name = "aat2870",
512 .owner = THIS_MODULE,
513 },
514 .probe = aat2870_i2c_probe,
515 .remove = aat2870_i2c_remove,
516 .suspend = aat2870_i2c_suspend,
517 .resume = aat2870_i2c_resume,
518 .id_table = aat2870_i2c_id_table,
519};
520
521static int __init aat2870_init(void)
522{
523 return i2c_add_driver(&aat2870_i2c_driver);
524}
525subsys_initcall(aat2870_init);
526
527static void __exit aat2870_exit(void)
528{
529 i2c_del_driver(&aat2870_i2c_driver);
530}
531module_exit(aat2870_exit);
532
533MODULE_DESCRIPTION("Core support for the AnalogicTech AAT2870");
534MODULE_LICENSE("GPL");
535MODULE_AUTHOR("Jin Park <jinyoungp@nvidia.com>");
diff --git a/include/linux/mfd/aat2870.h b/include/linux/mfd/aat2870.h
new file mode 100644
index 000000000000..89212df05622
--- /dev/null
+++ b/include/linux/mfd/aat2870.h
@@ -0,0 +1,181 @@
1/*
2 * linux/include/linux/mfd/aat2870.h
3 *
4 * Copyright (c) 2011, NVIDIA Corporation.
5 * Author: Jin Park <jinyoungp@nvidia.com>
6 *
7 * This program is free software; you can redistribute it and/or
8 * modify it under the terms of the GNU General Public License
9 * version 2 as published by the Free Software Foundation.
10 *
11 * This program is distributed in the hope that it will be useful, but
12 * WITHOUT ANY WARRANTY; without even the implied warranty of
13 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
14 * General Public License for more details.
15 *
16 * You should have received a copy of the GNU General Public License
17 * along with this program; if not, write to the Free Software
18 * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA
19 * 02110-1301 USA
20 */
21
22#ifndef __LINUX_MFD_AAT2870_H
23#define __LINUX_MFD_AAT2870_H
24
25#include <linux/debugfs.h>
26#include <linux/i2c.h>
27
28/* Register offsets */
29#define AAT2870_BL_CH_EN 0x00
30#define AAT2870_BLM 0x01
31#define AAT2870_BLS 0x02
32#define AAT2870_BL1 0x03
33#define AAT2870_BL2 0x04
34#define AAT2870_BL3 0x05
35#define AAT2870_BL4 0x06
36#define AAT2870_BL5 0x07
37#define AAT2870_BL6 0x08
38#define AAT2870_BL7 0x09
39#define AAT2870_BL8 0x0A
40#define AAT2870_FLR 0x0B
41#define AAT2870_FM 0x0C
42#define AAT2870_FS 0x0D
43#define AAT2870_ALS_CFG0 0x0E
44#define AAT2870_ALS_CFG1 0x0F
45#define AAT2870_ALS_CFG2 0x10
46#define AAT2870_AMB 0x11
47#define AAT2870_ALS0 0x12
48#define AAT2870_ALS1 0x13
49#define AAT2870_ALS2 0x14
50#define AAT2870_ALS3 0x15
51#define AAT2870_ALS4 0x16
52#define AAT2870_ALS5 0x17
53#define AAT2870_ALS6 0x18
54#define AAT2870_ALS7 0x19
55#define AAT2870_ALS8 0x1A
56#define AAT2870_ALS9 0x1B
57#define AAT2870_ALSA 0x1C
58#define AAT2870_ALSB 0x1D
59#define AAT2870_ALSC 0x1E
60#define AAT2870_ALSD 0x1F
61#define AAT2870_ALSE 0x20
62#define AAT2870_ALSF 0x21
63#define AAT2870_SUB_SET 0x22
64#define AAT2870_SUB_CTRL 0x23
65#define AAT2870_LDO_AB 0x24
66#define AAT2870_LDO_CD 0x25
67#define AAT2870_LDO_EN 0x26
68#define AAT2870_REG_NUM 0x27
69
70/* Device IDs */
71enum aat2870_id {
72 AAT2870_ID_BL,
73 AAT2870_ID_LDOA,
74 AAT2870_ID_LDOB,
75 AAT2870_ID_LDOC,
76 AAT2870_ID_LDOD
77};
78
79/* Backlight channels */
80#define AAT2870_BL_CH1 0x01
81#define AAT2870_BL_CH2 0x02
82#define AAT2870_BL_CH3 0x04
83#define AAT2870_BL_CH4 0x08
84#define AAT2870_BL_CH5 0x10
85#define AAT2870_BL_CH6 0x20
86#define AAT2870_BL_CH7 0x40
87#define AAT2870_BL_CH8 0x80
88#define AAT2870_BL_CH_ALL 0xFF
89
90/* Backlight current magnitude (mA) */
91enum aat2870_current {
92 AAT2870_CURRENT_0_45,
93 AAT2870_CURRENT_0_90,
94 AAT2870_CURRENT_1_80,
95 AAT2870_CURRENT_2_70,
96 AAT2870_CURRENT_3_60,
97 AAT2870_CURRENT_4_50,
98 AAT2870_CURRENT_5_40,
99 AAT2870_CURRENT_6_30,
100 AAT2870_CURRENT_7_20,
101 AAT2870_CURRENT_8_10,
102 AAT2870_CURRENT_9_00,
103 AAT2870_CURRENT_9_90,
104 AAT2870_CURRENT_10_8,
105 AAT2870_CURRENT_11_7,
106 AAT2870_CURRENT_12_6,
107 AAT2870_CURRENT_13_5,
108 AAT2870_CURRENT_14_4,
109 AAT2870_CURRENT_15_3,
110 AAT2870_CURRENT_16_2,
111 AAT2870_CURRENT_17_1,
112 AAT2870_CURRENT_18_0,
113 AAT2870_CURRENT_18_9,
114 AAT2870_CURRENT_19_8,
115 AAT2870_CURRENT_20_7,
116 AAT2870_CURRENT_21_6,
117 AAT2870_CURRENT_22_5,
118 AAT2870_CURRENT_23_4,
119 AAT2870_CURRENT_24_3,
120 AAT2870_CURRENT_25_2,
121 AAT2870_CURRENT_26_1,
122 AAT2870_CURRENT_27_0,
123 AAT2870_CURRENT_27_9
124};
125
126struct aat2870_register {
127 bool readable;
128 bool writeable;
129 u8 value;
130};
131
132struct aat2870_data {
133 struct device *dev;
134 struct i2c_client *client;
135
136 struct mutex io_lock;
137 struct aat2870_register *reg_cache; /* register cache */
138 int en_pin; /* enable GPIO pin (if < 0, ignore this value) */
139 bool is_enable;
140
141 /* init and uninit for platform specified */
142 int (*init)(struct aat2870_data *aat2870);
143 void (*uninit)(struct aat2870_data *aat2870);
144
145 /* i2c io funcntions */
146 int (*read)(struct aat2870_data *aat2870, u8 addr, u8 *val);
147 int (*write)(struct aat2870_data *aat2870, u8 addr, u8 val);
148 int (*update)(struct aat2870_data *aat2870, u8 addr, u8 mask, u8 val);
149
150 /* for debugfs */
151 struct dentry *dentry_root;
152 struct dentry *dentry_reg;
153};
154
155struct aat2870_subdev_info {
156 int id;
157 const char *name;
158 void *platform_data;
159};
160
161struct aat2870_platform_data {
162 int en_pin; /* enable GPIO pin (if < 0, ignore this value) */
163
164 struct aat2870_subdev_info *subdevs;
165 int num_subdevs;
166
167 /* init and uninit for platform specified */
168 int (*init)(struct aat2870_data *aat2870);
169 void (*uninit)(struct aat2870_data *aat2870);
170};
171
172struct aat2870_bl_platform_data {
173 /* backlight channels, default is AAT2870_BL_CH_ALL */
174 int channels;
175 /* backlight current magnitude, default is AAT2870_CURRENT_27_9 */
176 int max_current;
177 /* maximum brightness, default is 255 */
178 int max_brightness;
179};
180
181#endif /* __LINUX_MFD_AAT2870_H */