diff options
author | Dmitry Torokhov <dmitry.torokhov@gmail.com> | 2011-09-07 17:18:36 -0400 |
---|---|---|
committer | Dmitry Torokhov <dmitry.torokhov@gmail.com> | 2011-09-07 17:18:36 -0400 |
commit | 7e66eaf14e19c032433be7c4df3c892fa2a5282f (patch) | |
tree | 56b0d5f9d16eb18744e102f3f216715196cd62e6 /drivers/input/misc | |
parent | d3654d7ef3adad0083525cfb6fe27be62cb83d0d (diff) | |
parent | c6a389f123b9f68d605bb7e0f9b32ec1e3e14132 (diff) |
Merge commit 'v3.1-rc4' into next
Diffstat (limited to 'drivers/input/misc')
-rw-r--r-- | drivers/input/misc/Kconfig | 13 | ||||
-rw-r--r-- | drivers/input/misc/Makefile | 1 | ||||
-rw-r--r-- | drivers/input/misc/ad714x-i2c.c | 81 | ||||
-rw-r--r-- | drivers/input/misc/ad714x-spi.c | 68 | ||||
-rw-r--r-- | drivers/input/misc/ad714x.c | 116 | ||||
-rw-r--r-- | drivers/input/misc/ad714x.h | 35 | ||||
-rw-r--r-- | drivers/input/misc/kxtj9.c | 1 | ||||
-rw-r--r-- | drivers/input/misc/mma8450.c | 8 | ||||
-rw-r--r-- | drivers/input/misc/mpu3050.c | 2 | ||||
-rw-r--r-- | drivers/input/misc/pcspkr.c | 9 | ||||
-rw-r--r-- | drivers/input/misc/pmic8xxx-pwrkey.c | 3 | ||||
-rw-r--r-- | drivers/input/misc/twl4030-vibra.c | 12 | ||||
-rw-r--r-- | drivers/input/misc/twl6040-vibra.c | 423 |
13 files changed, 622 insertions, 150 deletions
diff --git a/drivers/input/misc/Kconfig b/drivers/input/misc/Kconfig index e141debb9d08..a1aa35a053b7 100644 --- a/drivers/input/misc/Kconfig +++ b/drivers/input/misc/Kconfig | |||
@@ -339,7 +339,7 @@ config INPUT_TWL4030_PWRBUTTON | |||
339 | config INPUT_TWL4030_VIBRA | 339 | config INPUT_TWL4030_VIBRA |
340 | tristate "Support for TWL4030 Vibrator" | 340 | tristate "Support for TWL4030 Vibrator" |
341 | depends on TWL4030_CORE | 341 | depends on TWL4030_CORE |
342 | select TWL4030_CODEC | 342 | select MFD_TWL4030_AUDIO |
343 | select INPUT_FF_MEMLESS | 343 | select INPUT_FF_MEMLESS |
344 | help | 344 | help |
345 | This option enables support for TWL4030 Vibrator Driver. | 345 | This option enables support for TWL4030 Vibrator Driver. |
@@ -347,6 +347,17 @@ config INPUT_TWL4030_VIBRA | |||
347 | To compile this driver as a module, choose M here. The module will | 347 | To compile this driver as a module, choose M here. The module will |
348 | be called twl4030_vibra. | 348 | be called twl4030_vibra. |
349 | 349 | ||
350 | config INPUT_TWL6040_VIBRA | ||
351 | tristate "Support for TWL6040 Vibrator" | ||
352 | depends on TWL4030_CORE | ||
353 | select TWL6040_CORE | ||
354 | select INPUT_FF_MEMLESS | ||
355 | help | ||
356 | This option enables support for TWL6040 Vibrator Driver. | ||
357 | |||
358 | To compile this driver as a module, choose M here. The module will | ||
359 | be called twl6040_vibra. | ||
360 | |||
350 | config INPUT_UINPUT | 361 | config INPUT_UINPUT |
351 | tristate "User level driver support" | 362 | tristate "User level driver support" |
352 | help | 363 | help |
diff --git a/drivers/input/misc/Makefile b/drivers/input/misc/Makefile index ac65eb22bcec..53a8d0faad52 100644 --- a/drivers/input/misc/Makefile +++ b/drivers/input/misc/Makefile | |||
@@ -45,6 +45,7 @@ obj-$(CONFIG_INPUT_SGI_BTNS) += sgi_btns.o | |||
45 | obj-$(CONFIG_INPUT_SPARCSPKR) += sparcspkr.o | 45 | obj-$(CONFIG_INPUT_SPARCSPKR) += sparcspkr.o |
46 | obj-$(CONFIG_INPUT_TWL4030_PWRBUTTON) += twl4030-pwrbutton.o | 46 | obj-$(CONFIG_INPUT_TWL4030_PWRBUTTON) += twl4030-pwrbutton.o |
47 | obj-$(CONFIG_INPUT_TWL4030_VIBRA) += twl4030-vibra.o | 47 | obj-$(CONFIG_INPUT_TWL4030_VIBRA) += twl4030-vibra.o |
48 | obj-$(CONFIG_INPUT_TWL6040_VIBRA) += twl6040-vibra.o | ||
48 | obj-$(CONFIG_INPUT_UINPUT) += uinput.o | 49 | obj-$(CONFIG_INPUT_UINPUT) += uinput.o |
49 | obj-$(CONFIG_INPUT_WISTRON_BTNS) += wistron_btns.o | 50 | obj-$(CONFIG_INPUT_WISTRON_BTNS) += wistron_btns.o |
50 | obj-$(CONFIG_INPUT_WM831X_ON) += wm831x-on.o | 51 | obj-$(CONFIG_INPUT_WM831X_ON) += wm831x-on.o |
diff --git a/drivers/input/misc/ad714x-i2c.c b/drivers/input/misc/ad714x-i2c.c index 45a6c9168f0a..56810fb4eadd 100644 --- a/drivers/input/misc/ad714x-i2c.c +++ b/drivers/input/misc/ad714x-i2c.c | |||
@@ -1,7 +1,7 @@ | |||
1 | /* | 1 | /* |
2 | * AD714X CapTouch Programmable Controller driver (I2C bus) | 2 | * AD714X CapTouch Programmable Controller driver (I2C bus) |
3 | * | 3 | * |
4 | * Copyright 2009 Analog Devices Inc. | 4 | * Copyright 2009-2011 Analog Devices Inc. |
5 | * | 5 | * |
6 | * Licensed under the GPL-2 or later. | 6 | * Licensed under the GPL-2 or later. |
7 | */ | 7 | */ |
@@ -27,54 +27,49 @@ static int ad714x_i2c_resume(struct device *dev) | |||
27 | 27 | ||
28 | static SIMPLE_DEV_PM_OPS(ad714x_i2c_pm, ad714x_i2c_suspend, ad714x_i2c_resume); | 28 | static SIMPLE_DEV_PM_OPS(ad714x_i2c_pm, ad714x_i2c_suspend, ad714x_i2c_resume); |
29 | 29 | ||
30 | static int ad714x_i2c_write(struct device *dev, unsigned short reg, | 30 | static int ad714x_i2c_write(struct ad714x_chip *chip, |
31 | unsigned short data) | 31 | unsigned short reg, unsigned short data) |
32 | { | 32 | { |
33 | struct i2c_client *client = to_i2c_client(dev); | 33 | struct i2c_client *client = to_i2c_client(chip->dev); |
34 | int ret = 0; | 34 | int error; |
35 | u8 *_reg = (u8 *)® | 35 | |
36 | u8 *_data = (u8 *)&data; | 36 | chip->xfer_buf[0] = cpu_to_be16(reg); |
37 | 37 | chip->xfer_buf[1] = cpu_to_be16(data); | |
38 | u8 tx[4] = { | 38 | |
39 | _reg[1], | 39 | error = i2c_master_send(client, (u8 *)chip->xfer_buf, |
40 | _reg[0], | 40 | 2 * sizeof(*chip->xfer_buf)); |
41 | _data[1], | 41 | if (unlikely(error < 0)) { |
42 | _data[0] | 42 | dev_err(&client->dev, "I2C write error: %d\n", error); |
43 | }; | 43 | return error; |
44 | 44 | } | |
45 | ret = i2c_master_send(client, tx, 4); | 45 | |
46 | if (ret < 0) | 46 | return 0; |
47 | dev_err(&client->dev, "I2C write error\n"); | ||
48 | |||
49 | return ret; | ||
50 | } | 47 | } |
51 | 48 | ||
52 | static int ad714x_i2c_read(struct device *dev, unsigned short reg, | 49 | static int ad714x_i2c_read(struct ad714x_chip *chip, |
53 | unsigned short *data) | 50 | unsigned short reg, unsigned short *data, size_t len) |
54 | { | 51 | { |
55 | struct i2c_client *client = to_i2c_client(dev); | 52 | struct i2c_client *client = to_i2c_client(chip->dev); |
56 | int ret = 0; | 53 | int i; |
57 | u8 *_reg = (u8 *)® | 54 | int error; |
58 | u8 *_data = (u8 *)data; | 55 | |
59 | 56 | chip->xfer_buf[0] = cpu_to_be16(reg); | |
60 | u8 tx[2] = { | 57 | |
61 | _reg[1], | 58 | error = i2c_master_send(client, (u8 *)chip->xfer_buf, |
62 | _reg[0] | 59 | sizeof(*chip->xfer_buf)); |
63 | }; | 60 | if (error >= 0) |
64 | u8 rx[2]; | 61 | error = i2c_master_recv(client, (u8 *)chip->xfer_buf, |
65 | 62 | len * sizeof(*chip->xfer_buf)); | |
66 | ret = i2c_master_send(client, tx, 2); | 63 | |
67 | if (ret >= 0) | 64 | if (unlikely(error < 0)) { |
68 | ret = i2c_master_recv(client, rx, 2); | 65 | dev_err(&client->dev, "I2C read error: %d\n", error); |
69 | 66 | return error; | |
70 | if (unlikely(ret < 0)) { | ||
71 | dev_err(&client->dev, "I2C read error\n"); | ||
72 | } else { | ||
73 | _data[0] = rx[1]; | ||
74 | _data[1] = rx[0]; | ||
75 | } | 67 | } |
76 | 68 | ||
77 | return ret; | 69 | for (i = 0; i < len; i++) |
70 | data[i] = be16_to_cpu(chip->xfer_buf[i]); | ||
71 | |||
72 | return 0; | ||
78 | } | 73 | } |
79 | 74 | ||
80 | static int __devinit ad714x_i2c_probe(struct i2c_client *client, | 75 | static int __devinit ad714x_i2c_probe(struct i2c_client *client, |
diff --git a/drivers/input/misc/ad714x-spi.c b/drivers/input/misc/ad714x-spi.c index 4120dd549305..875b50811361 100644 --- a/drivers/input/misc/ad714x-spi.c +++ b/drivers/input/misc/ad714x-spi.c | |||
@@ -1,12 +1,12 @@ | |||
1 | /* | 1 | /* |
2 | * AD714X CapTouch Programmable Controller driver (SPI bus) | 2 | * AD714X CapTouch Programmable Controller driver (SPI bus) |
3 | * | 3 | * |
4 | * Copyright 2009 Analog Devices Inc. | 4 | * Copyright 2009-2011 Analog Devices Inc. |
5 | * | 5 | * |
6 | * Licensed under the GPL-2 or later. | 6 | * Licensed under the GPL-2 or later. |
7 | */ | 7 | */ |
8 | 8 | ||
9 | #include <linux/input.h> /* BUS_I2C */ | 9 | #include <linux/input.h> /* BUS_SPI */ |
10 | #include <linux/module.h> | 10 | #include <linux/module.h> |
11 | #include <linux/spi/spi.h> | 11 | #include <linux/spi/spi.h> |
12 | #include <linux/pm.h> | 12 | #include <linux/pm.h> |
@@ -30,30 +30,68 @@ static int ad714x_spi_resume(struct device *dev) | |||
30 | 30 | ||
31 | static SIMPLE_DEV_PM_OPS(ad714x_spi_pm, ad714x_spi_suspend, ad714x_spi_resume); | 31 | static SIMPLE_DEV_PM_OPS(ad714x_spi_pm, ad714x_spi_suspend, ad714x_spi_resume); |
32 | 32 | ||
33 | static int ad714x_spi_read(struct device *dev, unsigned short reg, | 33 | static int ad714x_spi_read(struct ad714x_chip *chip, |
34 | unsigned short *data) | 34 | unsigned short reg, unsigned short *data, size_t len) |
35 | { | 35 | { |
36 | struct spi_device *spi = to_spi_device(dev); | 36 | struct spi_device *spi = to_spi_device(chip->dev); |
37 | unsigned short tx = AD714x_SPI_CMD_PREFIX | AD714x_SPI_READ | reg; | 37 | struct spi_message message; |
38 | struct spi_transfer xfer[2]; | ||
39 | int i; | ||
40 | int error; | ||
41 | |||
42 | spi_message_init(&message); | ||
43 | memset(xfer, 0, sizeof(xfer)); | ||
44 | |||
45 | chip->xfer_buf[0] = cpu_to_be16(AD714x_SPI_CMD_PREFIX | | ||
46 | AD714x_SPI_READ | reg); | ||
47 | xfer[0].tx_buf = &chip->xfer_buf[0]; | ||
48 | xfer[0].len = sizeof(chip->xfer_buf[0]); | ||
49 | spi_message_add_tail(&xfer[0], &message); | ||
50 | |||
51 | xfer[1].rx_buf = &chip->xfer_buf[1]; | ||
52 | xfer[1].len = sizeof(chip->xfer_buf[1]) * len; | ||
53 | spi_message_add_tail(&xfer[1], &message); | ||
54 | |||
55 | error = spi_sync(spi, &message); | ||
56 | if (unlikely(error)) { | ||
57 | dev_err(chip->dev, "SPI read error: %d\n", error); | ||
58 | return error; | ||
59 | } | ||
60 | |||
61 | for (i = 0; i < len; i++) | ||
62 | data[i] = be16_to_cpu(chip->xfer_buf[i + 1]); | ||
38 | 63 | ||
39 | return spi_write_then_read(spi, (u8 *)&tx, 2, (u8 *)data, 2); | 64 | return 0; |
40 | } | 65 | } |
41 | 66 | ||
42 | static int ad714x_spi_write(struct device *dev, unsigned short reg, | 67 | static int ad714x_spi_write(struct ad714x_chip *chip, |
43 | unsigned short data) | 68 | unsigned short reg, unsigned short data) |
44 | { | 69 | { |
45 | struct spi_device *spi = to_spi_device(dev); | 70 | struct spi_device *spi = to_spi_device(chip->dev); |
46 | unsigned short tx[2] = { | 71 | int error; |
47 | AD714x_SPI_CMD_PREFIX | reg, | 72 | |
48 | data | 73 | chip->xfer_buf[0] = cpu_to_be16(AD714x_SPI_CMD_PREFIX | reg); |
49 | }; | 74 | chip->xfer_buf[1] = cpu_to_be16(data); |
75 | |||
76 | error = spi_write(spi, (u8 *)chip->xfer_buf, | ||
77 | 2 * sizeof(*chip->xfer_buf)); | ||
78 | if (unlikely(error)) { | ||
79 | dev_err(chip->dev, "SPI write error: %d\n", error); | ||
80 | return error; | ||
81 | } | ||
50 | 82 | ||
51 | return spi_write(spi, (u8 *)tx, 4); | 83 | return 0; |
52 | } | 84 | } |
53 | 85 | ||
54 | static int __devinit ad714x_spi_probe(struct spi_device *spi) | 86 | static int __devinit ad714x_spi_probe(struct spi_device *spi) |
55 | { | 87 | { |
56 | struct ad714x_chip *chip; | 88 | struct ad714x_chip *chip; |
89 | int err; | ||
90 | |||
91 | spi->bits_per_word = 8; | ||
92 | err = spi_setup(spi); | ||
93 | if (err < 0) | ||
94 | return err; | ||
57 | 95 | ||
58 | chip = ad714x_probe(&spi->dev, BUS_SPI, spi->irq, | 96 | chip = ad714x_probe(&spi->dev, BUS_SPI, spi->irq, |
59 | ad714x_spi_read, ad714x_spi_write); | 97 | ad714x_spi_read, ad714x_spi_write); |
diff --git a/drivers/input/misc/ad714x.c b/drivers/input/misc/ad714x.c index c3a62c42cd28..ca42c7d2a3c7 100644 --- a/drivers/input/misc/ad714x.c +++ b/drivers/input/misc/ad714x.c | |||
@@ -1,7 +1,7 @@ | |||
1 | /* | 1 | /* |
2 | * AD714X CapTouch Programmable Controller driver supporting AD7142/3/7/8/7A | 2 | * AD714X CapTouch Programmable Controller driver supporting AD7142/3/7/8/7A |
3 | * | 3 | * |
4 | * Copyright 2009 Analog Devices Inc. | 4 | * Copyright 2009-2011 Analog Devices Inc. |
5 | * | 5 | * |
6 | * Licensed under the GPL-2 or later. | 6 | * Licensed under the GPL-2 or later. |
7 | */ | 7 | */ |
@@ -59,7 +59,6 @@ | |||
59 | #define STAGE11_AMBIENT 0x27D | 59 | #define STAGE11_AMBIENT 0x27D |
60 | 60 | ||
61 | #define PER_STAGE_REG_NUM 36 | 61 | #define PER_STAGE_REG_NUM 36 |
62 | #define STAGE_NUM 12 | ||
63 | #define STAGE_CFGREG_NUM 8 | 62 | #define STAGE_CFGREG_NUM 8 |
64 | #define SYS_CFGREG_NUM 8 | 63 | #define SYS_CFGREG_NUM 8 |
65 | 64 | ||
@@ -124,27 +123,6 @@ struct ad714x_driver_data { | |||
124 | * information to integrate all things which will be private data | 123 | * information to integrate all things which will be private data |
125 | * of spi/i2c device | 124 | * of spi/i2c device |
126 | */ | 125 | */ |
127 | struct ad714x_chip { | ||
128 | unsigned short h_state; | ||
129 | unsigned short l_state; | ||
130 | unsigned short c_state; | ||
131 | unsigned short adc_reg[STAGE_NUM]; | ||
132 | unsigned short amb_reg[STAGE_NUM]; | ||
133 | unsigned short sensor_val[STAGE_NUM]; | ||
134 | |||
135 | struct ad714x_platform_data *hw; | ||
136 | struct ad714x_driver_data *sw; | ||
137 | |||
138 | int irq; | ||
139 | struct device *dev; | ||
140 | ad714x_read_t read; | ||
141 | ad714x_write_t write; | ||
142 | |||
143 | struct mutex mutex; | ||
144 | |||
145 | unsigned product; | ||
146 | unsigned version; | ||
147 | }; | ||
148 | 126 | ||
149 | static void ad714x_use_com_int(struct ad714x_chip *ad714x, | 127 | static void ad714x_use_com_int(struct ad714x_chip *ad714x, |
150 | int start_stage, int end_stage) | 128 | int start_stage, int end_stage) |
@@ -154,13 +132,13 @@ static void ad714x_use_com_int(struct ad714x_chip *ad714x, | |||
154 | 132 | ||
155 | mask = ((1 << (end_stage + 1)) - 1) - ((1 << start_stage) - 1); | 133 | mask = ((1 << (end_stage + 1)) - 1) - ((1 << start_stage) - 1); |
156 | 134 | ||
157 | ad714x->read(ad714x->dev, STG_COM_INT_EN_REG, &data); | 135 | ad714x->read(ad714x, STG_COM_INT_EN_REG, &data, 1); |
158 | data |= 1 << end_stage; | 136 | data |= 1 << end_stage; |
159 | ad714x->write(ad714x->dev, STG_COM_INT_EN_REG, data); | 137 | ad714x->write(ad714x, STG_COM_INT_EN_REG, data); |
160 | 138 | ||
161 | ad714x->read(ad714x->dev, STG_HIGH_INT_EN_REG, &data); | 139 | ad714x->read(ad714x, STG_HIGH_INT_EN_REG, &data, 1); |
162 | data &= ~mask; | 140 | data &= ~mask; |
163 | ad714x->write(ad714x->dev, STG_HIGH_INT_EN_REG, data); | 141 | ad714x->write(ad714x, STG_HIGH_INT_EN_REG, data); |
164 | } | 142 | } |
165 | 143 | ||
166 | static void ad714x_use_thr_int(struct ad714x_chip *ad714x, | 144 | static void ad714x_use_thr_int(struct ad714x_chip *ad714x, |
@@ -171,13 +149,13 @@ static void ad714x_use_thr_int(struct ad714x_chip *ad714x, | |||
171 | 149 | ||
172 | mask = ((1 << (end_stage + 1)) - 1) - ((1 << start_stage) - 1); | 150 | mask = ((1 << (end_stage + 1)) - 1) - ((1 << start_stage) - 1); |
173 | 151 | ||
174 | ad714x->read(ad714x->dev, STG_COM_INT_EN_REG, &data); | 152 | ad714x->read(ad714x, STG_COM_INT_EN_REG, &data, 1); |
175 | data &= ~(1 << end_stage); | 153 | data &= ~(1 << end_stage); |
176 | ad714x->write(ad714x->dev, STG_COM_INT_EN_REG, data); | 154 | ad714x->write(ad714x, STG_COM_INT_EN_REG, data); |
177 | 155 | ||
178 | ad714x->read(ad714x->dev, STG_HIGH_INT_EN_REG, &data); | 156 | ad714x->read(ad714x, STG_HIGH_INT_EN_REG, &data, 1); |
179 | data |= mask; | 157 | data |= mask; |
180 | ad714x->write(ad714x->dev, STG_HIGH_INT_EN_REG, data); | 158 | ad714x->write(ad714x, STG_HIGH_INT_EN_REG, data); |
181 | } | 159 | } |
182 | 160 | ||
183 | static int ad714x_cal_highest_stage(struct ad714x_chip *ad714x, | 161 | static int ad714x_cal_highest_stage(struct ad714x_chip *ad714x, |
@@ -273,15 +251,16 @@ static void ad714x_slider_cal_sensor_val(struct ad714x_chip *ad714x, int idx) | |||
273 | struct ad714x_slider_plat *hw = &ad714x->hw->slider[idx]; | 251 | struct ad714x_slider_plat *hw = &ad714x->hw->slider[idx]; |
274 | int i; | 252 | int i; |
275 | 253 | ||
254 | ad714x->read(ad714x, CDC_RESULT_S0 + hw->start_stage, | ||
255 | &ad714x->adc_reg[hw->start_stage], | ||
256 | hw->end_stage - hw->start_stage + 1); | ||
257 | |||
276 | for (i = hw->start_stage; i <= hw->end_stage; i++) { | 258 | for (i = hw->start_stage; i <= hw->end_stage; i++) { |
277 | ad714x->read(ad714x->dev, CDC_RESULT_S0 + i, | 259 | ad714x->read(ad714x, STAGE0_AMBIENT + i * PER_STAGE_REG_NUM, |
278 | &ad714x->adc_reg[i]); | 260 | &ad714x->amb_reg[i], 1); |
279 | ad714x->read(ad714x->dev, | 261 | |
280 | STAGE0_AMBIENT + i * PER_STAGE_REG_NUM, | 262 | ad714x->sensor_val[i] = |
281 | &ad714x->amb_reg[i]); | 263 | abs(ad714x->adc_reg[i] - ad714x->amb_reg[i]); |
282 | |||
283 | ad714x->sensor_val[i] = abs(ad714x->adc_reg[i] - | ||
284 | ad714x->amb_reg[i]); | ||
285 | } | 264 | } |
286 | } | 265 | } |
287 | 266 | ||
@@ -444,15 +423,16 @@ static void ad714x_wheel_cal_sensor_val(struct ad714x_chip *ad714x, int idx) | |||
444 | struct ad714x_wheel_plat *hw = &ad714x->hw->wheel[idx]; | 423 | struct ad714x_wheel_plat *hw = &ad714x->hw->wheel[idx]; |
445 | int i; | 424 | int i; |
446 | 425 | ||
426 | ad714x->read(ad714x, CDC_RESULT_S0 + hw->start_stage, | ||
427 | &ad714x->adc_reg[hw->start_stage], | ||
428 | hw->end_stage - hw->start_stage + 1); | ||
429 | |||
447 | for (i = hw->start_stage; i <= hw->end_stage; i++) { | 430 | for (i = hw->start_stage; i <= hw->end_stage; i++) { |
448 | ad714x->read(ad714x->dev, CDC_RESULT_S0 + i, | 431 | ad714x->read(ad714x, STAGE0_AMBIENT + i * PER_STAGE_REG_NUM, |
449 | &ad714x->adc_reg[i]); | 432 | &ad714x->amb_reg[i], 1); |
450 | ad714x->read(ad714x->dev, | ||
451 | STAGE0_AMBIENT + i * PER_STAGE_REG_NUM, | ||
452 | &ad714x->amb_reg[i]); | ||
453 | if (ad714x->adc_reg[i] > ad714x->amb_reg[i]) | 433 | if (ad714x->adc_reg[i] > ad714x->amb_reg[i]) |
454 | ad714x->sensor_val[i] = ad714x->adc_reg[i] - | 434 | ad714x->sensor_val[i] = |
455 | ad714x->amb_reg[i]; | 435 | ad714x->adc_reg[i] - ad714x->amb_reg[i]; |
456 | else | 436 | else |
457 | ad714x->sensor_val[i] = 0; | 437 | ad714x->sensor_val[i] = 0; |
458 | } | 438 | } |
@@ -597,15 +577,16 @@ static void touchpad_cal_sensor_val(struct ad714x_chip *ad714x, int idx) | |||
597 | struct ad714x_touchpad_plat *hw = &ad714x->hw->touchpad[idx]; | 577 | struct ad714x_touchpad_plat *hw = &ad714x->hw->touchpad[idx]; |
598 | int i; | 578 | int i; |
599 | 579 | ||
580 | ad714x->read(ad714x, CDC_RESULT_S0 + hw->x_start_stage, | ||
581 | &ad714x->adc_reg[hw->x_start_stage], | ||
582 | hw->x_end_stage - hw->x_start_stage + 1); | ||
583 | |||
600 | for (i = hw->x_start_stage; i <= hw->x_end_stage; i++) { | 584 | for (i = hw->x_start_stage; i <= hw->x_end_stage; i++) { |
601 | ad714x->read(ad714x->dev, CDC_RESULT_S0 + i, | 585 | ad714x->read(ad714x, STAGE0_AMBIENT + i * PER_STAGE_REG_NUM, |
602 | &ad714x->adc_reg[i]); | 586 | &ad714x->amb_reg[i], 1); |
603 | ad714x->read(ad714x->dev, | ||
604 | STAGE0_AMBIENT + i * PER_STAGE_REG_NUM, | ||
605 | &ad714x->amb_reg[i]); | ||
606 | if (ad714x->adc_reg[i] > ad714x->amb_reg[i]) | 587 | if (ad714x->adc_reg[i] > ad714x->amb_reg[i]) |
607 | ad714x->sensor_val[i] = ad714x->adc_reg[i] - | 588 | ad714x->sensor_val[i] = |
608 | ad714x->amb_reg[i]; | 589 | ad714x->adc_reg[i] - ad714x->amb_reg[i]; |
609 | else | 590 | else |
610 | ad714x->sensor_val[i] = 0; | 591 | ad714x->sensor_val[i] = 0; |
611 | } | 592 | } |
@@ -891,7 +872,7 @@ static int ad714x_hw_detect(struct ad714x_chip *ad714x) | |||
891 | { | 872 | { |
892 | unsigned short data; | 873 | unsigned short data; |
893 | 874 | ||
894 | ad714x->read(ad714x->dev, AD714X_PARTID_REG, &data); | 875 | ad714x->read(ad714x, AD714X_PARTID_REG, &data, 1); |
895 | switch (data & 0xFFF0) { | 876 | switch (data & 0xFFF0) { |
896 | case AD7142_PARTID: | 877 | case AD7142_PARTID: |
897 | ad714x->product = 0x7142; | 878 | ad714x->product = 0x7142; |
@@ -940,23 +921,20 @@ static void ad714x_hw_init(struct ad714x_chip *ad714x) | |||
940 | for (i = 0; i < STAGE_NUM; i++) { | 921 | for (i = 0; i < STAGE_NUM; i++) { |
941 | reg_base = AD714X_STAGECFG_REG + i * STAGE_CFGREG_NUM; | 922 | reg_base = AD714X_STAGECFG_REG + i * STAGE_CFGREG_NUM; |
942 | for (j = 0; j < STAGE_CFGREG_NUM; j++) | 923 | for (j = 0; j < STAGE_CFGREG_NUM; j++) |
943 | ad714x->write(ad714x->dev, reg_base + j, | 924 | ad714x->write(ad714x, reg_base + j, |
944 | ad714x->hw->stage_cfg_reg[i][j]); | 925 | ad714x->hw->stage_cfg_reg[i][j]); |
945 | } | 926 | } |
946 | 927 | ||
947 | for (i = 0; i < SYS_CFGREG_NUM; i++) | 928 | for (i = 0; i < SYS_CFGREG_NUM; i++) |
948 | ad714x->write(ad714x->dev, AD714X_SYSCFG_REG + i, | 929 | ad714x->write(ad714x, AD714X_SYSCFG_REG + i, |
949 | ad714x->hw->sys_cfg_reg[i]); | 930 | ad714x->hw->sys_cfg_reg[i]); |
950 | for (i = 0; i < SYS_CFGREG_NUM; i++) | 931 | for (i = 0; i < SYS_CFGREG_NUM; i++) |
951 | ad714x->read(ad714x->dev, AD714X_SYSCFG_REG + i, | 932 | ad714x->read(ad714x, AD714X_SYSCFG_REG + i, &data, 1); |
952 | &data); | ||
953 | 933 | ||
954 | ad714x->write(ad714x->dev, AD714X_STG_CAL_EN_REG, 0xFFF); | 934 | ad714x->write(ad714x, AD714X_STG_CAL_EN_REG, 0xFFF); |
955 | 935 | ||
956 | /* clear all interrupts */ | 936 | /* clear all interrupts */ |
957 | ad714x->read(ad714x->dev, STG_LOW_INT_STA_REG, &data); | 937 | ad714x->read(ad714x, STG_LOW_INT_STA_REG, &ad714x->l_state, 3); |
958 | ad714x->read(ad714x->dev, STG_HIGH_INT_STA_REG, &data); | ||
959 | ad714x->read(ad714x->dev, STG_COM_INT_STA_REG, &data); | ||
960 | } | 938 | } |
961 | 939 | ||
962 | static irqreturn_t ad714x_interrupt_thread(int irq, void *data) | 940 | static irqreturn_t ad714x_interrupt_thread(int irq, void *data) |
@@ -966,9 +944,7 @@ static irqreturn_t ad714x_interrupt_thread(int irq, void *data) | |||
966 | 944 | ||
967 | mutex_lock(&ad714x->mutex); | 945 | mutex_lock(&ad714x->mutex); |
968 | 946 | ||
969 | ad714x->read(ad714x->dev, STG_LOW_INT_STA_REG, &ad714x->l_state); | 947 | ad714x->read(ad714x, STG_LOW_INT_STA_REG, &ad714x->l_state, 3); |
970 | ad714x->read(ad714x->dev, STG_HIGH_INT_STA_REG, &ad714x->h_state); | ||
971 | ad714x->read(ad714x->dev, STG_COM_INT_STA_REG, &ad714x->c_state); | ||
972 | 948 | ||
973 | for (i = 0; i < ad714x->hw->button_num; i++) | 949 | for (i = 0; i < ad714x->hw->button_num; i++) |
974 | ad714x_button_state_machine(ad714x, i); | 950 | ad714x_button_state_machine(ad714x, i); |
@@ -1245,7 +1221,7 @@ int ad714x_disable(struct ad714x_chip *ad714x) | |||
1245 | mutex_lock(&ad714x->mutex); | 1221 | mutex_lock(&ad714x->mutex); |
1246 | 1222 | ||
1247 | data = ad714x->hw->sys_cfg_reg[AD714X_PWR_CTRL] | 0x3; | 1223 | data = ad714x->hw->sys_cfg_reg[AD714X_PWR_CTRL] | 0x3; |
1248 | ad714x->write(ad714x->dev, AD714X_PWR_CTRL, data); | 1224 | ad714x->write(ad714x, AD714X_PWR_CTRL, data); |
1249 | 1225 | ||
1250 | mutex_unlock(&ad714x->mutex); | 1226 | mutex_unlock(&ad714x->mutex); |
1251 | 1227 | ||
@@ -1255,24 +1231,20 @@ EXPORT_SYMBOL(ad714x_disable); | |||
1255 | 1231 | ||
1256 | int ad714x_enable(struct ad714x_chip *ad714x) | 1232 | int ad714x_enable(struct ad714x_chip *ad714x) |
1257 | { | 1233 | { |
1258 | unsigned short data; | ||
1259 | |||
1260 | dev_dbg(ad714x->dev, "%s enter\n", __func__); | 1234 | dev_dbg(ad714x->dev, "%s enter\n", __func__); |
1261 | 1235 | ||
1262 | mutex_lock(&ad714x->mutex); | 1236 | mutex_lock(&ad714x->mutex); |
1263 | 1237 | ||
1264 | /* resume to non-shutdown mode */ | 1238 | /* resume to non-shutdown mode */ |
1265 | 1239 | ||
1266 | ad714x->write(ad714x->dev, AD714X_PWR_CTRL, | 1240 | ad714x->write(ad714x, AD714X_PWR_CTRL, |
1267 | ad714x->hw->sys_cfg_reg[AD714X_PWR_CTRL]); | 1241 | ad714x->hw->sys_cfg_reg[AD714X_PWR_CTRL]); |
1268 | 1242 | ||
1269 | /* make sure the interrupt output line is not low level after resume, | 1243 | /* make sure the interrupt output line is not low level after resume, |
1270 | * otherwise we will get no chance to enter falling-edge irq again | 1244 | * otherwise we will get no chance to enter falling-edge irq again |
1271 | */ | 1245 | */ |
1272 | 1246 | ||
1273 | ad714x->read(ad714x->dev, STG_LOW_INT_STA_REG, &data); | 1247 | ad714x->read(ad714x, STG_LOW_INT_STA_REG, &ad714x->l_state, 3); |
1274 | ad714x->read(ad714x->dev, STG_HIGH_INT_STA_REG, &data); | ||
1275 | ad714x->read(ad714x->dev, STG_COM_INT_STA_REG, &data); | ||
1276 | 1248 | ||
1277 | mutex_unlock(&ad714x->mutex); | 1249 | mutex_unlock(&ad714x->mutex); |
1278 | 1250 | ||
diff --git a/drivers/input/misc/ad714x.h b/drivers/input/misc/ad714x.h index 45c54fb13f07..3c85455aa66d 100644 --- a/drivers/input/misc/ad714x.h +++ b/drivers/input/misc/ad714x.h | |||
@@ -1,7 +1,7 @@ | |||
1 | /* | 1 | /* |
2 | * AD714X CapTouch Programmable Controller driver (bus interfaces) | 2 | * AD714X CapTouch Programmable Controller driver (bus interfaces) |
3 | * | 3 | * |
4 | * Copyright 2009 Analog Devices Inc. | 4 | * Copyright 2009-2011 Analog Devices Inc. |
5 | * | 5 | * |
6 | * Licensed under the GPL-2 or later. | 6 | * Licensed under the GPL-2 or later. |
7 | */ | 7 | */ |
@@ -11,11 +11,40 @@ | |||
11 | 11 | ||
12 | #include <linux/types.h> | 12 | #include <linux/types.h> |
13 | 13 | ||
14 | #define STAGE_NUM 12 | ||
15 | |||
14 | struct device; | 16 | struct device; |
17 | struct ad714x_platform_data; | ||
18 | struct ad714x_driver_data; | ||
15 | struct ad714x_chip; | 19 | struct ad714x_chip; |
16 | 20 | ||
17 | typedef int (*ad714x_read_t)(struct device *, unsigned short, unsigned short *); | 21 | typedef int (*ad714x_read_t)(struct ad714x_chip *, unsigned short, unsigned short *, size_t); |
18 | typedef int (*ad714x_write_t)(struct device *, unsigned short, unsigned short); | 22 | typedef int (*ad714x_write_t)(struct ad714x_chip *, unsigned short, unsigned short); |
23 | |||
24 | struct ad714x_chip { | ||
25 | unsigned short l_state; | ||
26 | unsigned short h_state; | ||
27 | unsigned short c_state; | ||
28 | unsigned short adc_reg[STAGE_NUM]; | ||
29 | unsigned short amb_reg[STAGE_NUM]; | ||
30 | unsigned short sensor_val[STAGE_NUM]; | ||
31 | |||
32 | struct ad714x_platform_data *hw; | ||
33 | struct ad714x_driver_data *sw; | ||
34 | |||
35 | int irq; | ||
36 | struct device *dev; | ||
37 | ad714x_read_t read; | ||
38 | ad714x_write_t write; | ||
39 | |||
40 | struct mutex mutex; | ||
41 | |||
42 | unsigned product; | ||
43 | unsigned version; | ||
44 | |||
45 | __be16 xfer_buf[16] ____cacheline_aligned; | ||
46 | |||
47 | }; | ||
19 | 48 | ||
20 | int ad714x_disable(struct ad714x_chip *ad714x); | 49 | int ad714x_disable(struct ad714x_chip *ad714x); |
21 | int ad714x_enable(struct ad714x_chip *ad714x); | 50 | int ad714x_enable(struct ad714x_chip *ad714x); |
diff --git a/drivers/input/misc/kxtj9.c b/drivers/input/misc/kxtj9.c index c456f63b6bae..783597a9a64a 100644 --- a/drivers/input/misc/kxtj9.c +++ b/drivers/input/misc/kxtj9.c | |||
@@ -21,6 +21,7 @@ | |||
21 | #include <linux/i2c.h> | 21 | #include <linux/i2c.h> |
22 | #include <linux/input.h> | 22 | #include <linux/input.h> |
23 | #include <linux/interrupt.h> | 23 | #include <linux/interrupt.h> |
24 | #include <linux/module.h> | ||
24 | #include <linux/slab.h> | 25 | #include <linux/slab.h> |
25 | #include <linux/input/kxtj9.h> | 26 | #include <linux/input/kxtj9.h> |
26 | #include <linux/input-polldev.h> | 27 | #include <linux/input-polldev.h> |
diff --git a/drivers/input/misc/mma8450.c b/drivers/input/misc/mma8450.c index 20f8f9284f02..0794778295fc 100644 --- a/drivers/input/misc/mma8450.c +++ b/drivers/input/misc/mma8450.c | |||
@@ -24,6 +24,7 @@ | |||
24 | #include <linux/delay.h> | 24 | #include <linux/delay.h> |
25 | #include <linux/i2c.h> | 25 | #include <linux/i2c.h> |
26 | #include <linux/input-polldev.h> | 26 | #include <linux/input-polldev.h> |
27 | #include <linux/of_device.h> | ||
27 | 28 | ||
28 | #define MMA8450_DRV_NAME "mma8450" | 29 | #define MMA8450_DRV_NAME "mma8450" |
29 | 30 | ||
@@ -229,10 +230,17 @@ static const struct i2c_device_id mma8450_id[] = { | |||
229 | }; | 230 | }; |
230 | MODULE_DEVICE_TABLE(i2c, mma8450_id); | 231 | MODULE_DEVICE_TABLE(i2c, mma8450_id); |
231 | 232 | ||
233 | static const struct of_device_id mma8450_dt_ids[] = { | ||
234 | { .compatible = "fsl,mma8450", }, | ||
235 | { /* sentinel */ } | ||
236 | }; | ||
237 | MODULE_DEVICE_TABLE(of, mma8450_dt_ids); | ||
238 | |||
232 | static struct i2c_driver mma8450_driver = { | 239 | static struct i2c_driver mma8450_driver = { |
233 | .driver = { | 240 | .driver = { |
234 | .name = MMA8450_DRV_NAME, | 241 | .name = MMA8450_DRV_NAME, |
235 | .owner = THIS_MODULE, | 242 | .owner = THIS_MODULE, |
243 | .of_match_table = mma8450_dt_ids, | ||
236 | }, | 244 | }, |
237 | .probe = mma8450_probe, | 245 | .probe = mma8450_probe, |
238 | .remove = __devexit_p(mma8450_remove), | 246 | .remove = __devexit_p(mma8450_remove), |
diff --git a/drivers/input/misc/mpu3050.c b/drivers/input/misc/mpu3050.c index b95fac15b2ea..f71dc728da58 100644 --- a/drivers/input/misc/mpu3050.c +++ b/drivers/input/misc/mpu3050.c | |||
@@ -282,7 +282,7 @@ err_free_irq: | |||
282 | err_pm_set_suspended: | 282 | err_pm_set_suspended: |
283 | pm_runtime_set_suspended(&client->dev); | 283 | pm_runtime_set_suspended(&client->dev); |
284 | err_free_mem: | 284 | err_free_mem: |
285 | input_unregister_device(idev); | 285 | input_free_device(idev); |
286 | kfree(sensor); | 286 | kfree(sensor); |
287 | return error; | 287 | return error; |
288 | } | 288 | } |
diff --git a/drivers/input/misc/pcspkr.c b/drivers/input/misc/pcspkr.c index f080dd31499b..34f4d2e0f50f 100644 --- a/drivers/input/misc/pcspkr.c +++ b/drivers/input/misc/pcspkr.c | |||
@@ -14,6 +14,7 @@ | |||
14 | 14 | ||
15 | #include <linux/kernel.h> | 15 | #include <linux/kernel.h> |
16 | #include <linux/module.h> | 16 | #include <linux/module.h> |
17 | #include <linux/i8253.h> | ||
17 | #include <linux/init.h> | 18 | #include <linux/init.h> |
18 | #include <linux/input.h> | 19 | #include <linux/input.h> |
19 | #include <linux/platform_device.h> | 20 | #include <linux/platform_device.h> |
@@ -25,14 +26,6 @@ MODULE_DESCRIPTION("PC Speaker beeper driver"); | |||
25 | MODULE_LICENSE("GPL"); | 26 | MODULE_LICENSE("GPL"); |
26 | MODULE_ALIAS("platform:pcspkr"); | 27 | MODULE_ALIAS("platform:pcspkr"); |
27 | 28 | ||
28 | #if defined(CONFIG_MIPS) || defined(CONFIG_X86) | ||
29 | /* Use the global PIT lock ! */ | ||
30 | #include <asm/i8253.h> | ||
31 | #else | ||
32 | #include <asm/8253pit.h> | ||
33 | static DEFINE_RAW_SPINLOCK(i8253_lock); | ||
34 | #endif | ||
35 | |||
36 | static int pcspkr_event(struct input_dev *dev, unsigned int type, unsigned int code, int value) | 29 | static int pcspkr_event(struct input_dev *dev, unsigned int type, unsigned int code, int value) |
37 | { | 30 | { |
38 | unsigned int count = 0; | 31 | unsigned int count = 0; |
diff --git a/drivers/input/misc/pmic8xxx-pwrkey.c b/drivers/input/misc/pmic8xxx-pwrkey.c index 97e07e786e41..b3cfb9c71e66 100644 --- a/drivers/input/misc/pmic8xxx-pwrkey.c +++ b/drivers/input/misc/pmic8xxx-pwrkey.c | |||
@@ -90,7 +90,8 @@ static int __devinit pmic8xxx_pwrkey_probe(struct platform_device *pdev) | |||
90 | unsigned int delay; | 90 | unsigned int delay; |
91 | u8 pon_cntl; | 91 | u8 pon_cntl; |
92 | struct pmic8xxx_pwrkey *pwrkey; | 92 | struct pmic8xxx_pwrkey *pwrkey; |
93 | const struct pm8xxx_pwrkey_platform_data *pdata = mfd_get_data(pdev); | 93 | const struct pm8xxx_pwrkey_platform_data *pdata = |
94 | dev_get_platdata(&pdev->dev); | ||
94 | 95 | ||
95 | if (!pdata) { | 96 | if (!pdata) { |
96 | dev_err(&pdev->dev, "power key platform data not supplied\n"); | 97 | dev_err(&pdev->dev, "power key platform data not supplied\n"); |
diff --git a/drivers/input/misc/twl4030-vibra.c b/drivers/input/misc/twl4030-vibra.c index 014dd4ad0d4f..3c1a432c14dc 100644 --- a/drivers/input/misc/twl4030-vibra.c +++ b/drivers/input/misc/twl4030-vibra.c | |||
@@ -28,7 +28,7 @@ | |||
28 | #include <linux/platform_device.h> | 28 | #include <linux/platform_device.h> |
29 | #include <linux/workqueue.h> | 29 | #include <linux/workqueue.h> |
30 | #include <linux/i2c/twl.h> | 30 | #include <linux/i2c/twl.h> |
31 | #include <linux/mfd/twl4030-codec.h> | 31 | #include <linux/mfd/twl4030-audio.h> |
32 | #include <linux/input.h> | 32 | #include <linux/input.h> |
33 | #include <linux/slab.h> | 33 | #include <linux/slab.h> |
34 | 34 | ||
@@ -67,7 +67,7 @@ static void vibra_enable(struct vibra_info *info) | |||
67 | { | 67 | { |
68 | u8 reg; | 68 | u8 reg; |
69 | 69 | ||
70 | twl4030_codec_enable_resource(TWL4030_CODEC_RES_POWER); | 70 | twl4030_audio_enable_resource(TWL4030_AUDIO_RES_POWER); |
71 | 71 | ||
72 | /* turn H-Bridge on */ | 72 | /* turn H-Bridge on */ |
73 | twl_i2c_read_u8(TWL4030_MODULE_AUDIO_VOICE, | 73 | twl_i2c_read_u8(TWL4030_MODULE_AUDIO_VOICE, |
@@ -75,7 +75,7 @@ static void vibra_enable(struct vibra_info *info) | |||
75 | twl_i2c_write_u8(TWL4030_MODULE_AUDIO_VOICE, | 75 | twl_i2c_write_u8(TWL4030_MODULE_AUDIO_VOICE, |
76 | (reg | TWL4030_VIBRA_EN), TWL4030_REG_VIBRA_CTL); | 76 | (reg | TWL4030_VIBRA_EN), TWL4030_REG_VIBRA_CTL); |
77 | 77 | ||
78 | twl4030_codec_enable_resource(TWL4030_CODEC_RES_APLL); | 78 | twl4030_audio_enable_resource(TWL4030_AUDIO_RES_APLL); |
79 | 79 | ||
80 | info->enabled = true; | 80 | info->enabled = true; |
81 | } | 81 | } |
@@ -90,8 +90,8 @@ static void vibra_disable(struct vibra_info *info) | |||
90 | twl_i2c_write_u8(TWL4030_MODULE_AUDIO_VOICE, | 90 | twl_i2c_write_u8(TWL4030_MODULE_AUDIO_VOICE, |
91 | (reg & ~TWL4030_VIBRA_EN), TWL4030_REG_VIBRA_CTL); | 91 | (reg & ~TWL4030_VIBRA_EN), TWL4030_REG_VIBRA_CTL); |
92 | 92 | ||
93 | twl4030_codec_disable_resource(TWL4030_CODEC_RES_APLL); | 93 | twl4030_audio_disable_resource(TWL4030_AUDIO_RES_APLL); |
94 | twl4030_codec_disable_resource(TWL4030_CODEC_RES_POWER); | 94 | twl4030_audio_disable_resource(TWL4030_AUDIO_RES_POWER); |
95 | 95 | ||
96 | info->enabled = false; | 96 | info->enabled = false; |
97 | } | 97 | } |
@@ -196,7 +196,7 @@ static SIMPLE_DEV_PM_OPS(twl4030_vibra_pm_ops, | |||
196 | 196 | ||
197 | static int __devinit twl4030_vibra_probe(struct platform_device *pdev) | 197 | static int __devinit twl4030_vibra_probe(struct platform_device *pdev) |
198 | { | 198 | { |
199 | struct twl4030_codec_vibra_data *pdata = pdev->dev.platform_data; | 199 | struct twl4030_vibra_data *pdata = pdev->dev.platform_data; |
200 | struct vibra_info *info; | 200 | struct vibra_info *info; |
201 | int ret; | 201 | int ret; |
202 | 202 | ||
diff --git a/drivers/input/misc/twl6040-vibra.c b/drivers/input/misc/twl6040-vibra.c new file mode 100644 index 000000000000..c43002e7ec72 --- /dev/null +++ b/drivers/input/misc/twl6040-vibra.c | |||
@@ -0,0 +1,423 @@ | |||
1 | /* | ||
2 | * twl6040-vibra.c - TWL6040 Vibrator driver | ||
3 | * | ||
4 | * Author: Jorge Eduardo Candelaria <jorge.candelaria@ti.com> | ||
5 | * Author: Misael Lopez Cruz <misael.lopez@ti.com> | ||
6 | * | ||
7 | * Copyright: (C) 2011 Texas Instruments, Inc. | ||
8 | * | ||
9 | * Based on twl4030-vibra.c by Henrik Saari <henrik.saari@nokia.com> | ||
10 | * Felipe Balbi <felipe.balbi@nokia.com> | ||
11 | * Jari Vanhala <ext-javi.vanhala@nokia.com> | ||
12 | * | ||
13 | * This program is free software; you can redistribute it and/or modify | ||
14 | * it under the terms of the GNU General Public License version 2 as | ||
15 | * published by the Free Software Foundation. | ||
16 | * | ||
17 | * This program is distributed in the hope that it will be useful, but | ||
18 | * WITHOUT ANY WARRANTY; without even the implied warranty of | ||
19 | * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU | ||
20 | * General Public License for more details. | ||
21 | * | ||
22 | * You should have received a copy of the GNU General Public License | ||
23 | * along with this program; if not, write to the Free Software | ||
24 | * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA | ||
25 | * 02110-1301 USA | ||
26 | * | ||
27 | */ | ||
28 | #include <linux/module.h> | ||
29 | #include <linux/platform_device.h> | ||
30 | #include <linux/workqueue.h> | ||
31 | #include <linux/i2c/twl.h> | ||
32 | #include <linux/mfd/twl6040.h> | ||
33 | #include <linux/slab.h> | ||
34 | #include <linux/delay.h> | ||
35 | #include <linux/regulator/consumer.h> | ||
36 | |||
37 | #define EFFECT_DIR_180_DEG 0x8000 | ||
38 | |||
39 | /* Recommended modulation index 85% */ | ||
40 | #define TWL6040_VIBRA_MOD 85 | ||
41 | |||
42 | #define TWL6040_NUM_SUPPLIES 2 | ||
43 | |||
44 | struct vibra_info { | ||
45 | struct device *dev; | ||
46 | struct input_dev *input_dev; | ||
47 | struct workqueue_struct *workqueue; | ||
48 | struct work_struct play_work; | ||
49 | struct mutex mutex; | ||
50 | int irq; | ||
51 | |||
52 | bool enabled; | ||
53 | int weak_speed; | ||
54 | int strong_speed; | ||
55 | int direction; | ||
56 | |||
57 | unsigned int vibldrv_res; | ||
58 | unsigned int vibrdrv_res; | ||
59 | unsigned int viblmotor_res; | ||
60 | unsigned int vibrmotor_res; | ||
61 | |||
62 | struct regulator_bulk_data supplies[TWL6040_NUM_SUPPLIES]; | ||
63 | |||
64 | struct twl6040 *twl6040; | ||
65 | }; | ||
66 | |||
67 | static irqreturn_t twl6040_vib_irq_handler(int irq, void *data) | ||
68 | { | ||
69 | struct vibra_info *info = data; | ||
70 | struct twl6040 *twl6040 = info->twl6040; | ||
71 | u8 status; | ||
72 | |||
73 | status = twl6040_reg_read(twl6040, TWL6040_REG_STATUS); | ||
74 | if (status & TWL6040_VIBLOCDET) { | ||
75 | dev_warn(info->dev, "Left Vibrator overcurrent detected\n"); | ||
76 | twl6040_clear_bits(twl6040, TWL6040_REG_VIBCTLL, | ||
77 | TWL6040_VIBENAL); | ||
78 | } | ||
79 | if (status & TWL6040_VIBROCDET) { | ||
80 | dev_warn(info->dev, "Right Vibrator overcurrent detected\n"); | ||
81 | twl6040_clear_bits(twl6040, TWL6040_REG_VIBCTLR, | ||
82 | TWL6040_VIBENAR); | ||
83 | } | ||
84 | |||
85 | return IRQ_HANDLED; | ||
86 | } | ||
87 | |||
88 | static void twl6040_vibra_enable(struct vibra_info *info) | ||
89 | { | ||
90 | struct twl6040 *twl6040 = info->twl6040; | ||
91 | int ret; | ||
92 | |||
93 | ret = regulator_bulk_enable(ARRAY_SIZE(info->supplies), info->supplies); | ||
94 | if (ret) { | ||
95 | dev_err(info->dev, "failed to enable regulators %d\n", ret); | ||
96 | return; | ||
97 | } | ||
98 | |||
99 | twl6040_power(info->twl6040, 1); | ||
100 | if (twl6040->rev <= TWL6040_REV_ES1_1) { | ||
101 | /* | ||
102 | * ERRATA: Disable overcurrent protection for at least | ||
103 | * 3ms when enabling vibrator drivers to avoid false | ||
104 | * overcurrent detection | ||
105 | */ | ||
106 | twl6040_reg_write(twl6040, TWL6040_REG_VIBCTLL, | ||
107 | TWL6040_VIBENAL | TWL6040_VIBCTRLL); | ||
108 | twl6040_reg_write(twl6040, TWL6040_REG_VIBCTLR, | ||
109 | TWL6040_VIBENAR | TWL6040_VIBCTRLR); | ||
110 | usleep_range(3000, 3500); | ||
111 | } | ||
112 | |||
113 | twl6040_reg_write(twl6040, TWL6040_REG_VIBCTLL, | ||
114 | TWL6040_VIBENAL); | ||
115 | twl6040_reg_write(twl6040, TWL6040_REG_VIBCTLR, | ||
116 | TWL6040_VIBENAR); | ||
117 | |||
118 | info->enabled = true; | ||
119 | } | ||
120 | |||
121 | static void twl6040_vibra_disable(struct vibra_info *info) | ||
122 | { | ||
123 | struct twl6040 *twl6040 = info->twl6040; | ||
124 | |||
125 | twl6040_reg_write(twl6040, TWL6040_REG_VIBCTLL, 0x00); | ||
126 | twl6040_reg_write(twl6040, TWL6040_REG_VIBCTLR, 0x00); | ||
127 | twl6040_power(info->twl6040, 0); | ||
128 | |||
129 | regulator_bulk_disable(ARRAY_SIZE(info->supplies), info->supplies); | ||
130 | |||
131 | info->enabled = false; | ||
132 | } | ||
133 | |||
134 | static u8 twl6040_vibra_code(int vddvib, int vibdrv_res, int motor_res, | ||
135 | int speed, int direction) | ||
136 | { | ||
137 | int vpk, max_code; | ||
138 | u8 vibdat; | ||
139 | |||
140 | /* output swing */ | ||
141 | vpk = (vddvib * motor_res * TWL6040_VIBRA_MOD) / | ||
142 | (100 * (vibdrv_res + motor_res)); | ||
143 | |||
144 | /* 50mV per VIBDAT code step */ | ||
145 | max_code = vpk / 50; | ||
146 | if (max_code > TWL6040_VIBDAT_MAX) | ||
147 | max_code = TWL6040_VIBDAT_MAX; | ||
148 | |||
149 | /* scale speed to max allowed code */ | ||
150 | vibdat = (u8)((speed * max_code) / USHRT_MAX); | ||
151 | |||
152 | /* 2's complement for direction > 180 degrees */ | ||
153 | vibdat *= direction; | ||
154 | |||
155 | return vibdat; | ||
156 | } | ||
157 | |||
158 | static void twl6040_vibra_set_effect(struct vibra_info *info) | ||
159 | { | ||
160 | struct twl6040 *twl6040 = info->twl6040; | ||
161 | u8 vibdatl, vibdatr; | ||
162 | int volt; | ||
163 | |||
164 | /* weak motor */ | ||
165 | volt = regulator_get_voltage(info->supplies[0].consumer) / 1000; | ||
166 | vibdatl = twl6040_vibra_code(volt, info->vibldrv_res, | ||
167 | info->viblmotor_res, | ||
168 | info->weak_speed, info->direction); | ||
169 | |||
170 | /* strong motor */ | ||
171 | volt = regulator_get_voltage(info->supplies[1].consumer) / 1000; | ||
172 | vibdatr = twl6040_vibra_code(volt, info->vibrdrv_res, | ||
173 | info->vibrmotor_res, | ||
174 | info->strong_speed, info->direction); | ||
175 | |||
176 | twl6040_reg_write(twl6040, TWL6040_REG_VIBDATL, vibdatl); | ||
177 | twl6040_reg_write(twl6040, TWL6040_REG_VIBDATR, vibdatr); | ||
178 | } | ||
179 | |||
180 | static void vibra_play_work(struct work_struct *work) | ||
181 | { | ||
182 | struct vibra_info *info = container_of(work, | ||
183 | struct vibra_info, play_work); | ||
184 | |||
185 | mutex_lock(&info->mutex); | ||
186 | |||
187 | if (info->weak_speed || info->strong_speed) { | ||
188 | if (!info->enabled) | ||
189 | twl6040_vibra_enable(info); | ||
190 | |||
191 | twl6040_vibra_set_effect(info); | ||
192 | } else if (info->enabled) | ||
193 | twl6040_vibra_disable(info); | ||
194 | |||
195 | mutex_unlock(&info->mutex); | ||
196 | } | ||
197 | |||
198 | static int vibra_play(struct input_dev *input, void *data, | ||
199 | struct ff_effect *effect) | ||
200 | { | ||
201 | struct vibra_info *info = input_get_drvdata(input); | ||
202 | int ret; | ||
203 | |||
204 | info->weak_speed = effect->u.rumble.weak_magnitude; | ||
205 | info->strong_speed = effect->u.rumble.strong_magnitude; | ||
206 | info->direction = effect->direction < EFFECT_DIR_180_DEG ? 1 : -1; | ||
207 | |||
208 | ret = queue_work(info->workqueue, &info->play_work); | ||
209 | if (!ret) { | ||
210 | dev_info(&input->dev, "work is already on queue\n"); | ||
211 | return ret; | ||
212 | } | ||
213 | |||
214 | return 0; | ||
215 | } | ||
216 | |||
217 | static void twl6040_vibra_close(struct input_dev *input) | ||
218 | { | ||
219 | struct vibra_info *info = input_get_drvdata(input); | ||
220 | |||
221 | cancel_work_sync(&info->play_work); | ||
222 | |||
223 | mutex_lock(&info->mutex); | ||
224 | |||
225 | if (info->enabled) | ||
226 | twl6040_vibra_disable(info); | ||
227 | |||
228 | mutex_unlock(&info->mutex); | ||
229 | } | ||
230 | |||
231 | #if CONFIG_PM_SLEEP | ||
232 | static int twl6040_vibra_suspend(struct device *dev) | ||
233 | { | ||
234 | struct platform_device *pdev = to_platform_device(dev); | ||
235 | struct vibra_info *info = platform_get_drvdata(pdev); | ||
236 | |||
237 | mutex_lock(&info->mutex); | ||
238 | |||
239 | if (info->enabled) | ||
240 | twl6040_vibra_disable(info); | ||
241 | |||
242 | mutex_unlock(&info->mutex); | ||
243 | |||
244 | return 0; | ||
245 | } | ||
246 | |||
247 | #endif | ||
248 | |||
249 | static SIMPLE_DEV_PM_OPS(twl6040_vibra_pm_ops, twl6040_vibra_suspend, NULL); | ||
250 | |||
251 | static int __devinit twl6040_vibra_probe(struct platform_device *pdev) | ||
252 | { | ||
253 | struct twl4030_vibra_data *pdata = pdev->dev.platform_data; | ||
254 | struct vibra_info *info; | ||
255 | int ret; | ||
256 | |||
257 | if (!pdata) { | ||
258 | dev_err(&pdev->dev, "platform_data not available\n"); | ||
259 | return -EINVAL; | ||
260 | } | ||
261 | |||
262 | info = kzalloc(sizeof(*info), GFP_KERNEL); | ||
263 | if (!info) { | ||
264 | dev_err(&pdev->dev, "couldn't allocate memory\n"); | ||
265 | return -ENOMEM; | ||
266 | } | ||
267 | |||
268 | info->dev = &pdev->dev; | ||
269 | info->twl6040 = dev_get_drvdata(pdev->dev.parent); | ||
270 | info->vibldrv_res = pdata->vibldrv_res; | ||
271 | info->vibrdrv_res = pdata->vibrdrv_res; | ||
272 | info->viblmotor_res = pdata->viblmotor_res; | ||
273 | info->vibrmotor_res = pdata->vibrmotor_res; | ||
274 | if ((!info->vibldrv_res && !info->viblmotor_res) || | ||
275 | (!info->vibrdrv_res && !info->vibrmotor_res)) { | ||
276 | dev_err(info->dev, "invalid vibra driver/motor resistance\n"); | ||
277 | ret = -EINVAL; | ||
278 | goto err_kzalloc; | ||
279 | } | ||
280 | |||
281 | info->irq = platform_get_irq(pdev, 0); | ||
282 | if (info->irq < 0) { | ||
283 | dev_err(info->dev, "invalid irq\n"); | ||
284 | ret = -EINVAL; | ||
285 | goto err_kzalloc; | ||
286 | } | ||
287 | |||
288 | mutex_init(&info->mutex); | ||
289 | |||
290 | info->input_dev = input_allocate_device(); | ||
291 | if (info->input_dev == NULL) { | ||
292 | dev_err(info->dev, "couldn't allocate input device\n"); | ||
293 | ret = -ENOMEM; | ||
294 | goto err_kzalloc; | ||
295 | } | ||
296 | |||
297 | input_set_drvdata(info->input_dev, info); | ||
298 | |||
299 | info->input_dev->name = "twl6040:vibrator"; | ||
300 | info->input_dev->id.version = 1; | ||
301 | info->input_dev->dev.parent = pdev->dev.parent; | ||
302 | info->input_dev->close = twl6040_vibra_close; | ||
303 | __set_bit(FF_RUMBLE, info->input_dev->ffbit); | ||
304 | |||
305 | ret = input_ff_create_memless(info->input_dev, NULL, vibra_play); | ||
306 | if (ret < 0) { | ||
307 | dev_err(info->dev, "couldn't register vibrator to FF\n"); | ||
308 | goto err_ialloc; | ||
309 | } | ||
310 | |||
311 | ret = input_register_device(info->input_dev); | ||
312 | if (ret < 0) { | ||
313 | dev_err(info->dev, "couldn't register input device\n"); | ||
314 | goto err_iff; | ||
315 | } | ||
316 | |||
317 | platform_set_drvdata(pdev, info); | ||
318 | |||
319 | ret = request_threaded_irq(info->irq, NULL, twl6040_vib_irq_handler, 0, | ||
320 | "twl6040_irq_vib", info); | ||
321 | if (ret) { | ||
322 | dev_err(info->dev, "VIB IRQ request failed: %d\n", ret); | ||
323 | goto err_irq; | ||
324 | } | ||
325 | |||
326 | info->supplies[0].supply = "vddvibl"; | ||
327 | info->supplies[1].supply = "vddvibr"; | ||
328 | ret = regulator_bulk_get(info->dev, ARRAY_SIZE(info->supplies), | ||
329 | info->supplies); | ||
330 | if (ret) { | ||
331 | dev_err(info->dev, "couldn't get regulators %d\n", ret); | ||
332 | goto err_regulator; | ||
333 | } | ||
334 | |||
335 | if (pdata->vddvibl_uV) { | ||
336 | ret = regulator_set_voltage(info->supplies[0].consumer, | ||
337 | pdata->vddvibl_uV, | ||
338 | pdata->vddvibl_uV); | ||
339 | if (ret) { | ||
340 | dev_err(info->dev, "failed to set VDDVIBL volt %d\n", | ||
341 | ret); | ||
342 | goto err_voltage; | ||
343 | } | ||
344 | } | ||
345 | |||
346 | if (pdata->vddvibr_uV) { | ||
347 | ret = regulator_set_voltage(info->supplies[1].consumer, | ||
348 | pdata->vddvibr_uV, | ||
349 | pdata->vddvibr_uV); | ||
350 | if (ret) { | ||
351 | dev_err(info->dev, "failed to set VDDVIBR volt %d\n", | ||
352 | ret); | ||
353 | goto err_voltage; | ||
354 | } | ||
355 | } | ||
356 | |||
357 | info->workqueue = alloc_workqueue("twl6040-vibra", 0, 0); | ||
358 | if (info->workqueue == NULL) { | ||
359 | dev_err(info->dev, "couldn't create workqueue\n"); | ||
360 | ret = -ENOMEM; | ||
361 | goto err_voltage; | ||
362 | } | ||
363 | INIT_WORK(&info->play_work, vibra_play_work); | ||
364 | |||
365 | return 0; | ||
366 | |||
367 | err_voltage: | ||
368 | regulator_bulk_free(ARRAY_SIZE(info->supplies), info->supplies); | ||
369 | err_regulator: | ||
370 | free_irq(info->irq, info); | ||
371 | err_irq: | ||
372 | input_unregister_device(info->input_dev); | ||
373 | info->input_dev = NULL; | ||
374 | err_iff: | ||
375 | if (info->input_dev) | ||
376 | input_ff_destroy(info->input_dev); | ||
377 | err_ialloc: | ||
378 | input_free_device(info->input_dev); | ||
379 | err_kzalloc: | ||
380 | kfree(info); | ||
381 | return ret; | ||
382 | } | ||
383 | |||
384 | static int __devexit twl6040_vibra_remove(struct platform_device *pdev) | ||
385 | { | ||
386 | struct vibra_info *info = platform_get_drvdata(pdev); | ||
387 | |||
388 | input_unregister_device(info->input_dev); | ||
389 | free_irq(info->irq, info); | ||
390 | regulator_bulk_free(ARRAY_SIZE(info->supplies), info->supplies); | ||
391 | destroy_workqueue(info->workqueue); | ||
392 | kfree(info); | ||
393 | |||
394 | return 0; | ||
395 | } | ||
396 | |||
397 | static struct platform_driver twl6040_vibra_driver = { | ||
398 | .probe = twl6040_vibra_probe, | ||
399 | .remove = __devexit_p(twl6040_vibra_remove), | ||
400 | .driver = { | ||
401 | .name = "twl6040-vibra", | ||
402 | .owner = THIS_MODULE, | ||
403 | .pm = &twl6040_vibra_pm_ops, | ||
404 | }, | ||
405 | }; | ||
406 | |||
407 | static int __init twl6040_vibra_init(void) | ||
408 | { | ||
409 | return platform_driver_register(&twl6040_vibra_driver); | ||
410 | } | ||
411 | module_init(twl6040_vibra_init); | ||
412 | |||
413 | static void __exit twl6040_vibra_exit(void) | ||
414 | { | ||
415 | platform_driver_unregister(&twl6040_vibra_driver); | ||
416 | } | ||
417 | module_exit(twl6040_vibra_exit); | ||
418 | |||
419 | MODULE_ALIAS("platform:twl6040-vibra"); | ||
420 | MODULE_DESCRIPTION("TWL6040 Vibra driver"); | ||
421 | MODULE_LICENSE("GPL"); | ||
422 | MODULE_AUTHOR("Jorge Eduardo Candelaria <jorge.candelaria@ti.com>"); | ||
423 | MODULE_AUTHOR("Misael Lopez Cruz <misael.lopez@ti.com>"); | ||