diff options
| author | Jonathan Herman <hermanjl@cs.unc.edu> | 2013-01-17 16:15:55 -0500 |
|---|---|---|
| committer | Jonathan Herman <hermanjl@cs.unc.edu> | 2013-01-17 16:15:55 -0500 |
| commit | 8dea78da5cee153b8af9c07a2745f6c55057fe12 (patch) | |
| tree | a8f4d49d63b1ecc92f2fddceba0655b2472c5bd9 /drivers/input/touchscreen | |
| parent | 406089d01562f1e2bf9f089fd7637009ebaad589 (diff) | |
Patched in Tegra support.
Diffstat (limited to 'drivers/input/touchscreen')
65 files changed, 2284 insertions, 7169 deletions
diff --git a/drivers/input/touchscreen/88pm860x-ts.c b/drivers/input/touchscreen/88pm860x-ts.c index c7068942ebe..b3aebc2166b 100644 --- a/drivers/input/touchscreen/88pm860x-ts.c +++ b/drivers/input/touchscreen/88pm860x-ts.c | |||
| @@ -10,7 +10,6 @@ | |||
| 10 | */ | 10 | */ |
| 11 | #include <linux/kernel.h> | 11 | #include <linux/kernel.h> |
| 12 | #include <linux/module.h> | 12 | #include <linux/module.h> |
| 13 | #include <linux/of.h> | ||
| 14 | #include <linux/platform_device.h> | 13 | #include <linux/platform_device.h> |
| 15 | #include <linux/i2c.h> | 14 | #include <linux/i2c.h> |
| 16 | #include <linux/input.h> | 15 | #include <linux/input.h> |
| @@ -114,69 +113,14 @@ static void pm860x_touch_close(struct input_dev *dev) | |||
| 114 | pm860x_set_bits(touch->i2c, MEAS_EN3, data, 0); | 113 | pm860x_set_bits(touch->i2c, MEAS_EN3, data, 0); |
| 115 | } | 114 | } |
| 116 | 115 | ||
| 117 | #ifdef CONFIG_OF | 116 | static int __devinit pm860x_touch_probe(struct platform_device *pdev) |
| 118 | static int pm860x_touch_dt_init(struct platform_device *pdev, | ||
| 119 | struct pm860x_chip *chip, | ||
| 120 | int *res_x) | ||
| 121 | { | ||
| 122 | struct device_node *np = pdev->dev.parent->of_node; | ||
| 123 | struct i2c_client *i2c = (chip->id == CHIP_PM8607) ? chip->client \ | ||
| 124 | : chip->companion; | ||
| 125 | int data, n, ret; | ||
| 126 | if (!np) | ||
| 127 | return -ENODEV; | ||
| 128 | np = of_find_node_by_name(np, "touch"); | ||
| 129 | if (!np) { | ||
| 130 | dev_err(&pdev->dev, "Can't find touch node\n"); | ||
| 131 | return -EINVAL; | ||
| 132 | } | ||
| 133 | /* set GPADC MISC1 register */ | ||
| 134 | data = 0; | ||
| 135 | if (!of_property_read_u32(np, "marvell,88pm860x-gpadc-prebias", &n)) | ||
| 136 | data |= (n << 1) & PM8607_GPADC_PREBIAS_MASK; | ||
| 137 | if (!of_property_read_u32(np, "marvell,88pm860x-gpadc-slot-cycle", &n)) | ||
| 138 | data |= (n << 3) & PM8607_GPADC_SLOT_CYCLE_MASK; | ||
| 139 | if (!of_property_read_u32(np, "marvell,88pm860x-gpadc-off-scale", &n)) | ||
| 140 | data |= (n << 5) & PM8607_GPADC_OFF_SCALE_MASK; | ||
| 141 | if (!of_property_read_u32(np, "marvell,88pm860x-gpadc-sw-cal", &n)) | ||
| 142 | data |= (n << 7) & PM8607_GPADC_SW_CAL_MASK; | ||
| 143 | if (data) { | ||
| 144 | ret = pm860x_reg_write(i2c, PM8607_GPADC_MISC1, data); | ||
| 145 | if (ret < 0) | ||
| 146 | return -EINVAL; | ||
| 147 | } | ||
| 148 | /* set tsi prebias time */ | ||
| 149 | if (!of_property_read_u32(np, "marvell,88pm860x-tsi-prebias", &data)) { | ||
| 150 | ret = pm860x_reg_write(i2c, PM8607_TSI_PREBIAS, data); | ||
| 151 | if (ret < 0) | ||
| 152 | return -EINVAL; | ||
| 153 | } | ||
| 154 | /* set prebias & prechg time of pen detect */ | ||
| 155 | data = 0; | ||
| 156 | if (!of_property_read_u32(np, "marvell,88pm860x-pen-prebias", &n)) | ||
| 157 | data |= n & PM8607_PD_PREBIAS_MASK; | ||
| 158 | if (!of_property_read_u32(np, "marvell,88pm860x-pen-prechg", &n)) | ||
| 159 | data |= n & PM8607_PD_PRECHG_MASK; | ||
| 160 | if (data) { | ||
| 161 | ret = pm860x_reg_write(i2c, PM8607_PD_PREBIAS, data); | ||
| 162 | if (ret < 0) | ||
| 163 | return -EINVAL; | ||
| 164 | } | ||
| 165 | of_property_read_u32(np, "marvell,88pm860x-resistor-X", res_x); | ||
| 166 | return 0; | ||
| 167 | } | ||
| 168 | #else | ||
| 169 | #define pm860x_touch_dt_init(x, y, z) (-1) | ||
| 170 | #endif | ||
| 171 | |||
| 172 | static int pm860x_touch_probe(struct platform_device *pdev) | ||
| 173 | { | 117 | { |
| 174 | struct pm860x_chip *chip = dev_get_drvdata(pdev->dev.parent); | 118 | struct pm860x_chip *chip = dev_get_drvdata(pdev->dev.parent); |
| 175 | struct pm860x_touch_pdata *pdata = pdev->dev.platform_data; | 119 | struct pm860x_platform_data *pm860x_pdata = \ |
| 120 | pdev->dev.parent->platform_data; | ||
| 121 | struct pm860x_touch_pdata *pdata = NULL; | ||
| 176 | struct pm860x_touch *touch; | 122 | struct pm860x_touch *touch; |
| 177 | struct i2c_client *i2c = (chip->id == CHIP_PM8607) ? chip->client \ | 123 | int irq, ret; |
| 178 | : chip->companion; | ||
| 179 | int irq, ret, res_x = 0, data = 0; | ||
| 180 | 124 | ||
| 181 | irq = platform_get_irq(pdev, 0); | 125 | irq = platform_get_irq(pdev, 0); |
| 182 | if (irq < 0) { | 126 | if (irq < 0) { |
| @@ -184,55 +128,16 @@ static int pm860x_touch_probe(struct platform_device *pdev) | |||
| 184 | return -EINVAL; | 128 | return -EINVAL; |
| 185 | } | 129 | } |
| 186 | 130 | ||
| 187 | if (pm860x_touch_dt_init(pdev, chip, &res_x)) { | 131 | if (!pm860x_pdata) { |
| 188 | if (pdata) { | 132 | dev_err(&pdev->dev, "platform data is missing\n"); |
| 189 | /* set GPADC MISC1 register */ | 133 | return -EINVAL; |
| 190 | data = 0; | 134 | } |
| 191 | data |= (pdata->gpadc_prebias << 1) | 135 | |
| 192 | & PM8607_GPADC_PREBIAS_MASK; | 136 | pdata = pm860x_pdata->touch; |
| 193 | data |= (pdata->slot_cycle << 3) | 137 | if (!pdata) { |
| 194 | & PM8607_GPADC_SLOT_CYCLE_MASK; | 138 | dev_err(&pdev->dev, "touchscreen data is missing\n"); |
| 195 | data |= (pdata->off_scale << 5) | 139 | return -EINVAL; |
| 196 | & PM8607_GPADC_OFF_SCALE_MASK; | ||
| 197 | data |= (pdata->sw_cal << 7) | ||
| 198 | & PM8607_GPADC_SW_CAL_MASK; | ||
| 199 | if (data) { | ||
| 200 | ret = pm860x_reg_write(i2c, | ||
| 201 | PM8607_GPADC_MISC1, data); | ||
| 202 | if (ret < 0) | ||
| 203 | return -EINVAL; | ||
| 204 | } | ||
| 205 | /* set tsi prebias time */ | ||
| 206 | if (pdata->tsi_prebias) { | ||
| 207 | data = pdata->tsi_prebias; | ||
| 208 | ret = pm860x_reg_write(i2c, | ||
| 209 | PM8607_TSI_PREBIAS, data); | ||
| 210 | if (ret < 0) | ||
| 211 | return -EINVAL; | ||
| 212 | } | ||
| 213 | /* set prebias & prechg time of pen detect */ | ||
| 214 | data = 0; | ||
| 215 | data |= pdata->pen_prebias | ||
| 216 | & PM8607_PD_PREBIAS_MASK; | ||
| 217 | data |= (pdata->pen_prechg << 5) | ||
| 218 | & PM8607_PD_PRECHG_MASK; | ||
| 219 | if (data) { | ||
| 220 | ret = pm860x_reg_write(i2c, | ||
| 221 | PM8607_PD_PREBIAS, data); | ||
| 222 | if (ret < 0) | ||
| 223 | return -EINVAL; | ||
| 224 | } | ||
| 225 | res_x = pdata->res_x; | ||
| 226 | } else { | ||
| 227 | dev_err(&pdev->dev, "failed to get platform data\n"); | ||
| 228 | return -EINVAL; | ||
| 229 | } | ||
| 230 | } | 140 | } |
| 231 | /* enable GPADC */ | ||
| 232 | ret = pm860x_set_bits(i2c, PM8607_GPADC_MISC1, PM8607_GPADC_EN, | ||
| 233 | PM8607_GPADC_EN); | ||
| 234 | if (ret) | ||
| 235 | return ret; | ||
| 236 | 141 | ||
| 237 | touch = kzalloc(sizeof(struct pm860x_touch), GFP_KERNEL); | 142 | touch = kzalloc(sizeof(struct pm860x_touch), GFP_KERNEL); |
| 238 | if (touch == NULL) | 143 | if (touch == NULL) |
| @@ -253,9 +158,9 @@ static int pm860x_touch_probe(struct platform_device *pdev) | |||
| 253 | touch->idev->open = pm860x_touch_open; | 158 | touch->idev->open = pm860x_touch_open; |
| 254 | touch->idev->close = pm860x_touch_close; | 159 | touch->idev->close = pm860x_touch_close; |
| 255 | touch->chip = chip; | 160 | touch->chip = chip; |
| 256 | touch->i2c = i2c; | 161 | touch->i2c = (chip->id == CHIP_PM8607) ? chip->client : chip->companion; |
| 257 | touch->irq = irq; | 162 | touch->irq = irq + chip->irq_base; |
| 258 | touch->res_x = res_x; | 163 | touch->res_x = pdata->res_x; |
| 259 | input_set_drvdata(touch->idev, touch); | 164 | input_set_drvdata(touch->idev, touch); |
| 260 | 165 | ||
| 261 | ret = request_threaded_irq(touch->irq, NULL, pm860x_touch_handler, | 166 | ret = request_threaded_irq(touch->irq, NULL, pm860x_touch_handler, |
| @@ -293,7 +198,7 @@ out: | |||
| 293 | return ret; | 198 | return ret; |
| 294 | } | 199 | } |
| 295 | 200 | ||
| 296 | static int pm860x_touch_remove(struct platform_device *pdev) | 201 | static int __devexit pm860x_touch_remove(struct platform_device *pdev) |
| 297 | { | 202 | { |
| 298 | struct pm860x_touch *touch = platform_get_drvdata(pdev); | 203 | struct pm860x_touch *touch = platform_get_drvdata(pdev); |
| 299 | 204 | ||
| @@ -310,9 +215,20 @@ static struct platform_driver pm860x_touch_driver = { | |||
| 310 | .owner = THIS_MODULE, | 215 | .owner = THIS_MODULE, |
| 311 | }, | 216 | }, |
| 312 | .probe = pm860x_touch_probe, | 217 | .probe = pm860x_touch_probe, |
| 313 | .remove = pm860x_touch_remove, | 218 | .remove = __devexit_p(pm860x_touch_remove), |
| 314 | }; | 219 | }; |
| 315 | module_platform_driver(pm860x_touch_driver); | 220 | |
| 221 | static int __init pm860x_touch_init(void) | ||
| 222 | { | ||
| 223 | return platform_driver_register(&pm860x_touch_driver); | ||
| 224 | } | ||
| 225 | module_init(pm860x_touch_init); | ||
| 226 | |||
| 227 | static void __exit pm860x_touch_exit(void) | ||
| 228 | { | ||
| 229 | platform_driver_unregister(&pm860x_touch_driver); | ||
| 230 | } | ||
| 231 | module_exit(pm860x_touch_exit); | ||
| 316 | 232 | ||
| 317 | MODULE_DESCRIPTION("Touchscreen driver for Marvell Semiconductor 88PM860x"); | 233 | MODULE_DESCRIPTION("Touchscreen driver for Marvell Semiconductor 88PM860x"); |
| 318 | MODULE_AUTHOR("Haojian Zhuang <haojian.zhuang@marvell.com>"); | 234 | MODULE_AUTHOR("Haojian Zhuang <haojian.zhuang@marvell.com>"); |
diff --git a/drivers/input/touchscreen/Kconfig b/drivers/input/touchscreen/Kconfig index 515cfe79054..a8fc74f730d 100644 --- a/drivers/input/touchscreen/Kconfig +++ b/drivers/input/touchscreen/Kconfig | |||
| @@ -98,18 +98,17 @@ config TOUCHSCREEN_ATMEL_MXT | |||
| 98 | To compile this driver as a module, choose M here: the | 98 | To compile this driver as a module, choose M here: the |
| 99 | module will be called atmel_mxt_ts. | 99 | module will be called atmel_mxt_ts. |
| 100 | 100 | ||
| 101 | config TOUCHSCREEN_AUO_PIXCIR | 101 | config TOUCHSCREEN_BITSY |
| 102 | tristate "AUO in-cell touchscreen using Pixcir ICs" | 102 | tristate "Compaq iPAQ H3600 (Bitsy) touchscreen" |
| 103 | depends on I2C | 103 | depends on SA1100_BITSY |
| 104 | depends on GPIOLIB | 104 | select SERIO |
| 105 | help | 105 | help |
| 106 | Say Y here if you have a AUO display with in-cell touchscreen | 106 | Say Y here if you have the h3600 (Bitsy) touchscreen. |
| 107 | using Pixcir ICs. | ||
| 108 | 107 | ||
| 109 | If unsure, say N. | 108 | If unsure, say N. |
| 110 | 109 | ||
| 111 | To compile this driver as a module, choose M here: the | 110 | To compile this driver as a module, choose M here: the |
| 112 | module will be called auo-pixcir-ts. | 111 | module will be called h3600_ts_input. |
| 113 | 112 | ||
| 114 | config TOUCHSCREEN_BU21013 | 113 | config TOUCHSCREEN_BU21013 |
| 115 | tristate "BU21013 based touch panel controllers" | 114 | tristate "BU21013 based touch panel controllers" |
| @@ -127,6 +126,7 @@ config TOUCHSCREEN_CY8CTMG110 | |||
| 127 | tristate "cy8ctmg110 touchscreen" | 126 | tristate "cy8ctmg110 touchscreen" |
| 128 | depends on I2C | 127 | depends on I2C |
| 129 | depends on GPIOLIB | 128 | depends on GPIOLIB |
| 129 | |||
| 130 | help | 130 | help |
| 131 | Say Y here if you have a cy8ctmg110 capacitive touchscreen on | 131 | Say Y here if you have a cy8ctmg110 capacitive touchscreen on |
| 132 | an AAVA device. | 132 | an AAVA device. |
| @@ -136,37 +136,6 @@ config TOUCHSCREEN_CY8CTMG110 | |||
| 136 | To compile this driver as a module, choose M here: the | 136 | To compile this driver as a module, choose M here: the |
| 137 | module will be called cy8ctmg110_ts. | 137 | module will be called cy8ctmg110_ts. |
| 138 | 138 | ||
| 139 | config TOUCHSCREEN_CYTTSP_CORE | ||
| 140 | tristate "Cypress TTSP touchscreen" | ||
| 141 | help | ||
| 142 | Say Y here if you have a touchscreen using controller from | ||
| 143 | the Cypress TrueTouch(tm) Standard Product family connected | ||
| 144 | to your system. You will also need to select appropriate | ||
| 145 | bus connection below. | ||
| 146 | |||
| 147 | If unsure, say N. | ||
| 148 | |||
| 149 | To compile this driver as a module, choose M here: the | ||
| 150 | module will be called cyttsp_core. | ||
| 151 | |||
| 152 | config TOUCHSCREEN_CYTTSP_I2C | ||
| 153 | tristate "support I2C bus connection" | ||
| 154 | depends on TOUCHSCREEN_CYTTSP_CORE && I2C | ||
| 155 | help | ||
| 156 | Say Y here if the touchscreen is connected via I2C bus. | ||
| 157 | |||
| 158 | To compile this driver as a module, choose M here: the | ||
| 159 | module will be called cyttsp_i2c. | ||
| 160 | |||
| 161 | config TOUCHSCREEN_CYTTSP_SPI | ||
| 162 | tristate "support SPI bus connection" | ||
| 163 | depends on TOUCHSCREEN_CYTTSP_CORE && SPI_MASTER | ||
| 164 | help | ||
| 165 | Say Y here if the touchscreen is connected via SPI bus. | ||
| 166 | |||
| 167 | To compile this driver as a module, choose M here: the | ||
| 168 | module will be called cyttsp_spi. | ||
| 169 | |||
| 170 | config TOUCHSCREEN_DA9034 | 139 | config TOUCHSCREEN_DA9034 |
| 171 | tristate "Touchscreen support for Dialog Semiconductor DA9034" | 140 | tristate "Touchscreen support for Dialog Semiconductor DA9034" |
| 172 | depends on PMIC_DA903X | 141 | depends on PMIC_DA903X |
| @@ -175,23 +144,6 @@ config TOUCHSCREEN_DA9034 | |||
| 175 | Say Y here to enable the support for the touchscreen found | 144 | Say Y here to enable the support for the touchscreen found |
| 176 | on Dialog Semiconductor DA9034 PMIC. | 145 | on Dialog Semiconductor DA9034 PMIC. |
| 177 | 146 | ||
| 178 | If unsure, say N. | ||
| 179 | |||
| 180 | To compile this driver as a module, choose M here: the | ||
| 181 | module will be called da9034-ts. | ||
| 182 | |||
| 183 | config TOUCHSCREEN_DA9052 | ||
| 184 | tristate "Dialog DA9052/DA9053 TSI" | ||
| 185 | depends on PMIC_DA9052 | ||
| 186 | help | ||
| 187 | Say Y here to support the touchscreen found on Dialog Semiconductor | ||
| 188 | DA9052-BC and DA9053-AA/Bx PMICs. | ||
| 189 | |||
| 190 | If unsure, say N. | ||
| 191 | |||
| 192 | To compile this driver as a module, choose M here: the | ||
| 193 | module will be called da9052_tsi. | ||
| 194 | |||
| 195 | config TOUCHSCREEN_DYNAPRO | 147 | config TOUCHSCREEN_DYNAPRO |
| 196 | tristate "Dynapro serial touchscreen" | 148 | tristate "Dynapro serial touchscreen" |
| 197 | select SERIO | 149 | select SERIO |
| @@ -225,16 +177,6 @@ config TOUCHSCREEN_EETI | |||
| 225 | To compile this driver as a module, choose M here: the | 177 | To compile this driver as a module, choose M here: the |
| 226 | module will be called eeti_ts. | 178 | module will be called eeti_ts. |
| 227 | 179 | ||
| 228 | config TOUCHSCREEN_EGALAX | ||
| 229 | tristate "EETI eGalax multi-touch panel support" | ||
| 230 | depends on I2C && OF | ||
| 231 | help | ||
| 232 | Say Y here to enable support for I2C connected EETI | ||
| 233 | eGalax multi-touch panels. | ||
| 234 | |||
| 235 | To compile this driver as a module, choose M here: the | ||
| 236 | module will be called egalax_ts. | ||
| 237 | |||
| 238 | config TOUCHSCREEN_FUJITSU | 180 | config TOUCHSCREEN_FUJITSU |
| 239 | tristate "Fujitsu serial touchscreen" | 181 | tristate "Fujitsu serial touchscreen" |
| 240 | select SERIO | 182 | select SERIO |
| @@ -248,24 +190,9 @@ config TOUCHSCREEN_FUJITSU | |||
| 248 | To compile this driver as a module, choose M here: the | 190 | To compile this driver as a module, choose M here: the |
| 249 | module will be called fujitsu-ts. | 191 | module will be called fujitsu-ts. |
| 250 | 192 | ||
| 251 | config TOUCHSCREEN_ILI210X | ||
| 252 | tristate "Ilitek ILI210X based touchscreen" | ||
| 253 | depends on I2C | ||
| 254 | help | ||
| 255 | Say Y here if you have a ILI210X based touchscreen | ||
| 256 | controller. This driver supports models ILI2102, | ||
| 257 | ILI2102s, ILI2103, ILI2103s and ILI2105. | ||
| 258 | Such kind of chipsets can be found in Amazon Kindle Fire | ||
| 259 | touchscreens. | ||
| 260 | |||
| 261 | If unsure, say N. | ||
| 262 | |||
| 263 | To compile this driver as a module, choose M here: the | ||
| 264 | module will be called ili210x. | ||
| 265 | |||
| 266 | config TOUCHSCREEN_S3C2410 | 193 | config TOUCHSCREEN_S3C2410 |
| 267 | tristate "Samsung S3C2410/generic touchscreen input driver" | 194 | tristate "Samsung S3C2410/generic touchscreen input driver" |
| 268 | depends on ARCH_S3C24XX || SAMSUNG_DEV_TS | 195 | depends on ARCH_S3C2410 || SAMSUNG_DEV_TS |
| 269 | select S3C_ADC | 196 | select S3C_ADC |
| 270 | help | 197 | help |
| 271 | Say Y here if you have the s3c2410 touchscreen. | 198 | Say Y here if you have the s3c2410 touchscreen. |
| @@ -311,18 +238,6 @@ config TOUCHSCREEN_WACOM_W8001 | |||
| 311 | To compile this driver as a module, choose M here: the | 238 | To compile this driver as a module, choose M here: the |
| 312 | module will be called wacom_w8001. | 239 | module will be called wacom_w8001. |
| 313 | 240 | ||
| 314 | config TOUCHSCREEN_WACOM_I2C | ||
| 315 | tristate "Wacom Tablet support (I2C)" | ||
| 316 | depends on I2C | ||
| 317 | help | ||
| 318 | Say Y here if you want to use the I2C version of the Wacom | ||
| 319 | Pen Tablet. | ||
| 320 | |||
| 321 | If unsure, say N. | ||
| 322 | |||
| 323 | To compile this driver as a module, choose M here: the module | ||
| 324 | will be called wacom_i2c. | ||
| 325 | |||
| 326 | config TOUCHSCREEN_LPC32XX | 241 | config TOUCHSCREEN_LPC32XX |
| 327 | tristate "LPC32XX touchscreen controller" | 242 | tristate "LPC32XX touchscreen controller" |
| 328 | depends on ARCH_LPC32XX | 243 | depends on ARCH_LPC32XX |
| @@ -357,18 +272,6 @@ config TOUCHSCREEN_MCS5000 | |||
| 357 | To compile this driver as a module, choose M here: the | 272 | To compile this driver as a module, choose M here: the |
| 358 | module will be called mcs5000_ts. | 273 | module will be called mcs5000_ts. |
| 359 | 274 | ||
| 360 | config TOUCHSCREEN_MMS114 | ||
| 361 | tristate "MELFAS MMS114 touchscreen" | ||
| 362 | depends on I2C | ||
| 363 | help | ||
| 364 | Say Y here if you have the MELFAS MMS114 touchscreen controller | ||
| 365 | chip in your system. | ||
| 366 | |||
| 367 | If unsure, say N. | ||
| 368 | |||
| 369 | To compile this driver as a module, choose M here: the | ||
| 370 | module will be called mms114. | ||
| 371 | |||
| 372 | config TOUCHSCREEN_MTOUCH | 275 | config TOUCHSCREEN_MTOUCH |
| 373 | tristate "MicroTouch serial touchscreens" | 276 | tristate "MicroTouch serial touchscreens" |
| 374 | select SERIO | 277 | select SERIO |
| @@ -460,19 +363,6 @@ config TOUCHSCREEN_PENMOUNT | |||
| 460 | To compile this driver as a module, choose M here: the | 363 | To compile this driver as a module, choose M here: the |
| 461 | module will be called penmount. | 364 | module will be called penmount. |
| 462 | 365 | ||
| 463 | config TOUCHSCREEN_EDT_FT5X06 | ||
| 464 | tristate "EDT FocalTech FT5x06 I2C Touchscreen support" | ||
| 465 | depends on I2C | ||
| 466 | help | ||
| 467 | Say Y here if you have an EDT "Polytouch" touchscreen based | ||
| 468 | on the FocalTech FT5x06 family of controllers connected to | ||
| 469 | your system. | ||
| 470 | |||
| 471 | If unsure, say N. | ||
| 472 | |||
| 473 | To compile this driver as a module, choose M here: the | ||
| 474 | module will be called edt-ft5x06. | ||
| 475 | |||
| 476 | config TOUCHSCREEN_MIGOR | 366 | config TOUCHSCREEN_MIGOR |
| 477 | tristate "Renesas MIGO-R touchscreen" | 367 | tristate "Renesas MIGO-R touchscreen" |
| 478 | depends on SH_MIGOR && I2C | 368 | depends on SH_MIGOR && I2C |
| @@ -484,6 +374,19 @@ config TOUCHSCREEN_MIGOR | |||
| 484 | To compile this driver as a module, choose M here: the | 374 | To compile this driver as a module, choose M here: the |
| 485 | module will be called migor_ts. | 375 | module will be called migor_ts. |
| 486 | 376 | ||
| 377 | config TOUCHSCREEN_PANJIT_I2C | ||
| 378 | tristate "PANJIT I2C touchscreen driver" | ||
| 379 | depends on I2C | ||
| 380 | default n | ||
| 381 | help | ||
| 382 | Say Y here to enable PANJIT I2C capacitive touchscreen support, | ||
| 383 | covering devices such as the MGG1010AI06 and EGG1010AI06 | ||
| 384 | |||
| 385 | If unsure, say N | ||
| 386 | |||
| 387 | To compile this driver as a module, choose M here: the module will | ||
| 388 | be called panjit_i2c. | ||
| 389 | |||
| 487 | config TOUCHSCREEN_TNETV107X | 390 | config TOUCHSCREEN_TNETV107X |
| 488 | tristate "TI TNETV107X touchscreen support" | 391 | tristate "TI TNETV107X touchscreen support" |
| 489 | depends on ARCH_DAVINCI_TNETV107X | 392 | depends on ARCH_DAVINCI_TNETV107X |
| @@ -493,6 +396,12 @@ config TOUCHSCREEN_TNETV107X | |||
| 493 | To compile this driver as a module, choose M here: the | 396 | To compile this driver as a module, choose M here: the |
| 494 | module will be called tnetv107x-ts. | 397 | module will be called tnetv107x-ts. |
| 495 | 398 | ||
| 399 | config TOUCHSCREEN_SYNAPTICS_I2C_RMI | ||
| 400 | tristate "Synaptics i2c touchscreen" | ||
| 401 | depends on I2C | ||
| 402 | help | ||
| 403 | This enables support for Synaptics RMI over I2C based touchscreens. | ||
| 404 | |||
| 496 | config TOUCHSCREEN_TOUCHRIGHT | 405 | config TOUCHSCREEN_TOUCHRIGHT |
| 497 | tristate "Touchright serial touchscreen" | 406 | tristate "Touchright serial touchscreen" |
| 498 | select SERIO | 407 | select SERIO |
| @@ -517,24 +426,12 @@ config TOUCHSCREEN_TOUCHWIN | |||
| 517 | To compile this driver as a module, choose M here: the | 426 | To compile this driver as a module, choose M here: the |
| 518 | module will be called touchwin. | 427 | module will be called touchwin. |
| 519 | 428 | ||
| 520 | config TOUCHSCREEN_TI_AM335X_TSC | ||
| 521 | tristate "TI Touchscreen Interface" | ||
| 522 | depends on MFD_TI_AM335X_TSCADC | ||
| 523 | help | ||
| 524 | Say Y here if you have 4/5/8 wire touchscreen controller | ||
| 525 | to be connected to the ADC controller on your TI AM335x SoC. | ||
| 526 | |||
| 527 | If unsure, say N. | ||
| 528 | |||
| 529 | To compile this driver as a module, choose M here: the | ||
| 530 | module will be called ti_am335x_tsc. | ||
| 531 | |||
| 532 | config TOUCHSCREEN_ATMEL_TSADCC | 429 | config TOUCHSCREEN_ATMEL_TSADCC |
| 533 | tristate "Atmel Touchscreen Interface" | 430 | tristate "Atmel Touchscreen Interface" |
| 534 | depends on ARCH_AT91 | 431 | depends on ARCH_AT91SAM9RL || ARCH_AT91SAM9G45 |
| 535 | help | 432 | help |
| 536 | Say Y here if you have a 4-wire touchscreen connected to the | 433 | Say Y here if you have a 4-wire touchscreen connected to the |
| 537 | ADC Controller on your Atmel SoC. | 434 | ADC Controller on your Atmel SoC (such as the AT91SAM9RL). |
| 538 | 435 | ||
| 539 | If unsure, say N. | 436 | If unsure, say N. |
| 540 | 437 | ||
| @@ -557,18 +454,6 @@ config TOUCHSCREEN_UCB1400 | |||
| 557 | To compile this driver as a module, choose M here: the | 454 | To compile this driver as a module, choose M here: the |
| 558 | module will be called ucb1400_ts. | 455 | module will be called ucb1400_ts. |
| 559 | 456 | ||
| 560 | config TOUCHSCREEN_PIXCIR | ||
| 561 | tristate "PIXCIR I2C touchscreens" | ||
| 562 | depends on I2C | ||
| 563 | help | ||
| 564 | Say Y here if you have a pixcir i2c touchscreen | ||
| 565 | controller. | ||
| 566 | |||
| 567 | If unsure, say N. | ||
| 568 | |||
| 569 | To compile this driver as a module, choose M here: the | ||
| 570 | module will be called pixcir_i2c_ts. | ||
| 571 | |||
| 572 | config TOUCHSCREEN_WM831X | 457 | config TOUCHSCREEN_WM831X |
| 573 | tristate "Support for WM831x touchscreen controllers" | 458 | tristate "Support for WM831x touchscreen controllers" |
| 574 | depends on MFD_WM831X | 459 | depends on MFD_WM831X |
| @@ -675,9 +560,6 @@ config TOUCHSCREEN_USB_COMPOSITE | |||
| 675 | - GoTop Super_Q2/GogoPen/PenPower tablets | 560 | - GoTop Super_Q2/GogoPen/PenPower tablets |
| 676 | - JASTEC USB Touch Controller/DigiTech DTR-02U | 561 | - JASTEC USB Touch Controller/DigiTech DTR-02U |
| 677 | - Zytronic controllers | 562 | - Zytronic controllers |
| 678 | - Elo TouchSystems 2700 IntelliTouch | ||
| 679 | - EasyTouch USB Touch Controller from Data Modul | ||
| 680 | - e2i (Mimo monitors) | ||
| 681 | 563 | ||
| 682 | Have a look at <http://linux.chapter7.ch/touchkit/> for | 564 | Have a look at <http://linux.chapter7.ch/touchkit/> for |
| 683 | a usage description and the required user-space stuff. | 565 | a usage description and the required user-space stuff. |
| @@ -757,14 +639,9 @@ config TOUCHSCREEN_USB_JASTEC | |||
| 757 | bool "JASTEC/DigiTech DTR-02U USB touch controller device support" if EXPERT | 639 | bool "JASTEC/DigiTech DTR-02U USB touch controller device support" if EXPERT |
| 758 | depends on TOUCHSCREEN_USB_COMPOSITE | 640 | depends on TOUCHSCREEN_USB_COMPOSITE |
| 759 | 641 | ||
| 760 | config TOUCHSCREEN_USB_ELO | ||
| 761 | default y | ||
| 762 | bool "Elo TouchSystems 2700 IntelliTouch controller device support" if EXPERT | ||
| 763 | depends on TOUCHSCREEN_USB_COMPOSITE | ||
| 764 | |||
| 765 | config TOUCHSCREEN_USB_E2I | 642 | config TOUCHSCREEN_USB_E2I |
| 766 | default y | 643 | default y |
| 767 | bool "e2i Touchscreen controller (e.g. from Mimo 740)" if EXPERT | 644 | bool "e2i Touchscreen controller (e.g. from Mimo 740)" |
| 768 | depends on TOUCHSCREEN_USB_COMPOSITE | 645 | depends on TOUCHSCREEN_USB_COMPOSITE |
| 769 | 646 | ||
| 770 | config TOUCHSCREEN_USB_ZYTRONIC | 647 | config TOUCHSCREEN_USB_ZYTRONIC |
| @@ -782,14 +659,6 @@ config TOUCHSCREEN_USB_NEXIO | |||
| 782 | bool "NEXIO/iNexio device support" if EXPERT | 659 | bool "NEXIO/iNexio device support" if EXPERT |
| 783 | depends on TOUCHSCREEN_USB_COMPOSITE | 660 | depends on TOUCHSCREEN_USB_COMPOSITE |
| 784 | 661 | ||
| 785 | config TOUCHSCREEN_USB_EASYTOUCH | ||
| 786 | default y | ||
| 787 | bool "EasyTouch USB Touch controller device support" if EMBEDDED | ||
| 788 | depends on TOUCHSCREEN_USB_COMPOSITE | ||
| 789 | help | ||
| 790 | Say Y here if you have an EasyTouch USB Touch controller. | ||
| 791 | If unsure, say N. | ||
| 792 | |||
| 793 | config TOUCHSCREEN_TOUCHIT213 | 662 | config TOUCHSCREEN_TOUCHIT213 |
| 794 | tristate "Sahara TouchIT-213 touchscreen" | 663 | tristate "Sahara TouchIT-213 touchscreen" |
| 795 | select SERIO | 664 | select SERIO |
| @@ -801,18 +670,6 @@ config TOUCHSCREEN_TOUCHIT213 | |||
| 801 | To compile this driver as a module, choose M here: the | 670 | To compile this driver as a module, choose M here: the |
| 802 | module will be called touchit213. | 671 | module will be called touchit213. |
| 803 | 672 | ||
| 804 | config TOUCHSCREEN_TSC_SERIO | ||
| 805 | tristate "TSC-10/25/40 serial touchscreen support" | ||
| 806 | select SERIO | ||
| 807 | help | ||
| 808 | Say Y here if you have a TSC-10, 25 or 40 serial touchscreen connected | ||
| 809 | to your system. | ||
| 810 | |||
| 811 | If unsure, say N. | ||
| 812 | |||
| 813 | To compile this driver as a module, choose M here: the | ||
| 814 | module will be called tsc40. | ||
| 815 | |||
| 816 | config TOUCHSCREEN_TSC2005 | 673 | config TOUCHSCREEN_TSC2005 |
| 817 | tristate "TSC2005 based touchscreens" | 674 | tristate "TSC2005 based touchscreens" |
| 818 | depends on SPI_MASTER && GENERIC_HARDIRQS | 675 | depends on SPI_MASTER && GENERIC_HARDIRQS |
| @@ -888,4 +745,29 @@ config TOUCHSCREEN_TPS6507X | |||
| 888 | To compile this driver as a module, choose M here: the | 745 | To compile this driver as a module, choose M here: the |
| 889 | module will be called tps6507x_ts. | 746 | module will be called tps6507x_ts. |
| 890 | 747 | ||
| 748 | config TOUCHSCREEN_RM31080A | ||
| 749 | tristate "RAYDIUM_31080A based touchscreens" | ||
| 750 | depends on SPI_MASTER | ||
| 751 | help | ||
| 752 | Say Y here if you have a touchscreen interface using the | ||
| 753 | RAYDIUM_T31080A controller, and your board-specific initialization | ||
| 754 | code includes that in its table of SPI devices. | ||
| 755 | |||
| 756 | If unsure, say N (but it's safe to say "Y"). | ||
| 757 | |||
| 758 | To compile this driver as a module, choose M here: the | ||
| 759 | module will be called RAYDIUM_31080A. | ||
| 760 | |||
| 761 | config TOUCHSCREEN_SYN_RMI4_SPI | ||
| 762 | tristate "RMI4 SPI Support" | ||
| 763 | depends on SPI_MASTER | ||
| 764 | help | ||
| 765 | Say Y here if you want to support RMI4 devices connect | ||
| 766 | to an SPI bus. | ||
| 767 | |||
| 768 | If unsure, say Y. | ||
| 769 | |||
| 770 | To compile this driver as a module, choose M here: the | ||
| 771 | module will be called rmi-spi. | ||
| 772 | |||
| 891 | endif | 773 | endif |
diff --git a/drivers/input/touchscreen/Makefile b/drivers/input/touchscreen/Makefile index 6bfbeab67c9..9c42d2100b5 100644 --- a/drivers/input/touchscreen/Makefile +++ b/drivers/input/touchscreen/Makefile | |||
| @@ -14,23 +14,16 @@ obj-$(CONFIG_TOUCHSCREEN_AD7879_SPI) += ad7879-spi.o | |||
| 14 | obj-$(CONFIG_TOUCHSCREEN_ADS7846) += ads7846.o | 14 | obj-$(CONFIG_TOUCHSCREEN_ADS7846) += ads7846.o |
| 15 | obj-$(CONFIG_TOUCHSCREEN_ATMEL_MXT) += atmel_mxt_ts.o | 15 | obj-$(CONFIG_TOUCHSCREEN_ATMEL_MXT) += atmel_mxt_ts.o |
| 16 | obj-$(CONFIG_TOUCHSCREEN_ATMEL_TSADCC) += atmel_tsadcc.o | 16 | obj-$(CONFIG_TOUCHSCREEN_ATMEL_TSADCC) += atmel_tsadcc.o |
| 17 | obj-$(CONFIG_TOUCHSCREEN_AUO_PIXCIR) += auo-pixcir-ts.o | 17 | obj-$(CONFIG_TOUCHSCREEN_BITSY) += h3600_ts_input.o |
| 18 | obj-$(CONFIG_TOUCHSCREEN_BU21013) += bu21013_ts.o | 18 | obj-$(CONFIG_TOUCHSCREEN_BU21013) += bu21013_ts.o |
| 19 | obj-$(CONFIG_TOUCHSCREEN_CY8CTMG110) += cy8ctmg110_ts.o | 19 | obj-$(CONFIG_TOUCHSCREEN_CY8CTMG110) += cy8ctmg110_ts.o |
| 20 | obj-$(CONFIG_TOUCHSCREEN_CYTTSP_CORE) += cyttsp_core.o | ||
| 21 | obj-$(CONFIG_TOUCHSCREEN_CYTTSP_I2C) += cyttsp_i2c.o | ||
| 22 | obj-$(CONFIG_TOUCHSCREEN_CYTTSP_SPI) += cyttsp_spi.o | ||
| 23 | obj-$(CONFIG_TOUCHSCREEN_DA9034) += da9034-ts.o | 20 | obj-$(CONFIG_TOUCHSCREEN_DA9034) += da9034-ts.o |
| 24 | obj-$(CONFIG_TOUCHSCREEN_DA9052) += da9052_tsi.o | ||
| 25 | obj-$(CONFIG_TOUCHSCREEN_DYNAPRO) += dynapro.o | 21 | obj-$(CONFIG_TOUCHSCREEN_DYNAPRO) += dynapro.o |
| 26 | obj-$(CONFIG_TOUCHSCREEN_EDT_FT5X06) += edt-ft5x06.o | ||
| 27 | obj-$(CONFIG_TOUCHSCREEN_HAMPSHIRE) += hampshire.o | 22 | obj-$(CONFIG_TOUCHSCREEN_HAMPSHIRE) += hampshire.o |
| 28 | obj-$(CONFIG_TOUCHSCREEN_GUNZE) += gunze.o | 23 | obj-$(CONFIG_TOUCHSCREEN_GUNZE) += gunze.o |
| 29 | obj-$(CONFIG_TOUCHSCREEN_EETI) += eeti_ts.o | 24 | obj-$(CONFIG_TOUCHSCREEN_EETI) += eeti_ts.o |
| 30 | obj-$(CONFIG_TOUCHSCREEN_ELO) += elo.o | 25 | obj-$(CONFIG_TOUCHSCREEN_ELO) += elo.o |
| 31 | obj-$(CONFIG_TOUCHSCREEN_EGALAX) += egalax_ts.o | ||
| 32 | obj-$(CONFIG_TOUCHSCREEN_FUJITSU) += fujitsu_ts.o | 26 | obj-$(CONFIG_TOUCHSCREEN_FUJITSU) += fujitsu_ts.o |
| 33 | obj-$(CONFIG_TOUCHSCREEN_ILI210X) += ili210x.o | ||
| 34 | obj-$(CONFIG_TOUCHSCREEN_INEXIO) += inexio.o | 27 | obj-$(CONFIG_TOUCHSCREEN_INEXIO) += inexio.o |
| 35 | obj-$(CONFIG_TOUCHSCREEN_INTEL_MID) += intel-mid-touch.o | 28 | obj-$(CONFIG_TOUCHSCREEN_INTEL_MID) += intel-mid-touch.o |
| 36 | obj-$(CONFIG_TOUCHSCREEN_LPC32XX) += lpc32xx_ts.o | 29 | obj-$(CONFIG_TOUCHSCREEN_LPC32XX) += lpc32xx_ts.o |
| @@ -38,30 +31,27 @@ obj-$(CONFIG_TOUCHSCREEN_MAX11801) += max11801_ts.o | |||
| 38 | obj-$(CONFIG_TOUCHSCREEN_MC13783) += mc13783_ts.o | 31 | obj-$(CONFIG_TOUCHSCREEN_MC13783) += mc13783_ts.o |
| 39 | obj-$(CONFIG_TOUCHSCREEN_MCS5000) += mcs5000_ts.o | 32 | obj-$(CONFIG_TOUCHSCREEN_MCS5000) += mcs5000_ts.o |
| 40 | obj-$(CONFIG_TOUCHSCREEN_MIGOR) += migor_ts.o | 33 | obj-$(CONFIG_TOUCHSCREEN_MIGOR) += migor_ts.o |
| 41 | obj-$(CONFIG_TOUCHSCREEN_MMS114) += mms114.o | ||
| 42 | obj-$(CONFIG_TOUCHSCREEN_MTOUCH) += mtouch.o | 34 | obj-$(CONFIG_TOUCHSCREEN_MTOUCH) += mtouch.o |
| 43 | obj-$(CONFIG_TOUCHSCREEN_MK712) += mk712.o | 35 | obj-$(CONFIG_TOUCHSCREEN_MK712) += mk712.o |
| 44 | obj-$(CONFIG_TOUCHSCREEN_HP600) += hp680_ts_input.o | 36 | obj-$(CONFIG_TOUCHSCREEN_HP600) += hp680_ts_input.o |
| 45 | obj-$(CONFIG_TOUCHSCREEN_HP7XX) += jornada720_ts.o | 37 | obj-$(CONFIG_TOUCHSCREEN_HP7XX) += jornada720_ts.o |
| 46 | obj-$(CONFIG_TOUCHSCREEN_HTCPEN) += htcpen.o | 38 | obj-$(CONFIG_TOUCHSCREEN_HTCPEN) += htcpen.o |
| 47 | obj-$(CONFIG_TOUCHSCREEN_USB_COMPOSITE) += usbtouchscreen.o | 39 | obj-$(CONFIG_TOUCHSCREEN_USB_COMPOSITE) += usbtouchscreen.o |
| 40 | obj-$(CONFIG_TOUCHSCREEN_PANJIT_I2C) += panjit_i2c.o | ||
| 48 | obj-$(CONFIG_TOUCHSCREEN_PCAP) += pcap_ts.o | 41 | obj-$(CONFIG_TOUCHSCREEN_PCAP) += pcap_ts.o |
| 49 | obj-$(CONFIG_TOUCHSCREEN_PENMOUNT) += penmount.o | 42 | obj-$(CONFIG_TOUCHSCREEN_PENMOUNT) += penmount.o |
| 50 | obj-$(CONFIG_TOUCHSCREEN_PIXCIR) += pixcir_i2c_ts.o | ||
| 51 | obj-$(CONFIG_TOUCHSCREEN_S3C2410) += s3c2410_ts.o | 43 | obj-$(CONFIG_TOUCHSCREEN_S3C2410) += s3c2410_ts.o |
| 52 | obj-$(CONFIG_TOUCHSCREEN_ST1232) += st1232.o | 44 | obj-$(CONFIG_TOUCHSCREEN_ST1232) += st1232.o |
| 53 | obj-$(CONFIG_TOUCHSCREEN_STMPE) += stmpe-ts.o | 45 | obj-$(CONFIG_TOUCHSCREEN_STMPE) += stmpe-ts.o |
| 54 | obj-$(CONFIG_TOUCHSCREEN_TI_AM335X_TSC) += ti_am335x_tsc.o | ||
| 55 | obj-$(CONFIG_TOUCHSCREEN_TNETV107X) += tnetv107x-ts.o | 46 | obj-$(CONFIG_TOUCHSCREEN_TNETV107X) += tnetv107x-ts.o |
| 47 | obj-$(CONFIG_TOUCHSCREEN_SYNAPTICS_I2C_RMI) += synaptics_i2c_rmi.o | ||
| 56 | obj-$(CONFIG_TOUCHSCREEN_TOUCHIT213) += touchit213.o | 48 | obj-$(CONFIG_TOUCHSCREEN_TOUCHIT213) += touchit213.o |
| 57 | obj-$(CONFIG_TOUCHSCREEN_TOUCHRIGHT) += touchright.o | 49 | obj-$(CONFIG_TOUCHSCREEN_TOUCHRIGHT) += touchright.o |
| 58 | obj-$(CONFIG_TOUCHSCREEN_TOUCHWIN) += touchwin.o | 50 | obj-$(CONFIG_TOUCHSCREEN_TOUCHWIN) += touchwin.o |
| 59 | obj-$(CONFIG_TOUCHSCREEN_TSC_SERIO) += tsc40.o | ||
| 60 | obj-$(CONFIG_TOUCHSCREEN_TSC2005) += tsc2005.o | 51 | obj-$(CONFIG_TOUCHSCREEN_TSC2005) += tsc2005.o |
| 61 | obj-$(CONFIG_TOUCHSCREEN_TSC2007) += tsc2007.o | 52 | obj-$(CONFIG_TOUCHSCREEN_TSC2007) += tsc2007.o |
| 62 | obj-$(CONFIG_TOUCHSCREEN_UCB1400) += ucb1400_ts.o | 53 | obj-$(CONFIG_TOUCHSCREEN_UCB1400) += ucb1400_ts.o |
| 63 | obj-$(CONFIG_TOUCHSCREEN_WACOM_W8001) += wacom_w8001.o | 54 | obj-$(CONFIG_TOUCHSCREEN_WACOM_W8001) += wacom_w8001.o |
| 64 | obj-$(CONFIG_TOUCHSCREEN_WACOM_I2C) += wacom_i2c.o | ||
| 65 | obj-$(CONFIG_TOUCHSCREEN_WM831X) += wm831x-ts.o | 55 | obj-$(CONFIG_TOUCHSCREEN_WM831X) += wm831x-ts.o |
| 66 | obj-$(CONFIG_TOUCHSCREEN_WM97XX) += wm97xx-ts.o | 56 | obj-$(CONFIG_TOUCHSCREEN_WM97XX) += wm97xx-ts.o |
| 67 | wm97xx-ts-$(CONFIG_TOUCHSCREEN_WM9705) += wm9705.o | 57 | wm97xx-ts-$(CONFIG_TOUCHSCREEN_WM9705) += wm9705.o |
| @@ -72,3 +62,5 @@ obj-$(CONFIG_TOUCHSCREEN_WM97XX_MAINSTONE) += mainstone-wm97xx.o | |||
| 72 | obj-$(CONFIG_TOUCHSCREEN_WM97XX_ZYLONITE) += zylonite-wm97xx.o | 62 | obj-$(CONFIG_TOUCHSCREEN_WM97XX_ZYLONITE) += zylonite-wm97xx.o |
| 73 | obj-$(CONFIG_TOUCHSCREEN_W90X900) += w90p910_ts.o | 63 | obj-$(CONFIG_TOUCHSCREEN_W90X900) += w90p910_ts.o |
| 74 | obj-$(CONFIG_TOUCHSCREEN_TPS6507X) += tps6507x-ts.o | 64 | obj-$(CONFIG_TOUCHSCREEN_TPS6507X) += tps6507x-ts.o |
| 65 | obj-$(CONFIG_TOUCHSCREEN_RM31080A) += rm31080a_ts.o | ||
| 66 | obj-$(CONFIG_TOUCHSCREEN_SYN_RMI4_SPI) += rmi4/ | ||
diff --git a/drivers/input/touchscreen/ad7877.c b/drivers/input/touchscreen/ad7877.c index 23fa829b869..714d4e0f9f9 100644 --- a/drivers/input/touchscreen/ad7877.c +++ b/drivers/input/touchscreen/ad7877.c | |||
| @@ -45,7 +45,6 @@ | |||
| 45 | #include <linux/slab.h> | 45 | #include <linux/slab.h> |
| 46 | #include <linux/spi/spi.h> | 46 | #include <linux/spi/spi.h> |
| 47 | #include <linux/spi/ad7877.h> | 47 | #include <linux/spi/ad7877.h> |
| 48 | #include <linux/module.h> | ||
| 49 | #include <asm/irq.h> | 48 | #include <asm/irq.h> |
| 50 | 49 | ||
| 51 | #define TS_PEN_UP_TIMEOUT msecs_to_jiffies(100) | 50 | #define TS_PEN_UP_TIMEOUT msecs_to_jiffies(100) |
| @@ -488,10 +487,10 @@ static ssize_t ad7877_disable_store(struct device *dev, | |||
| 488 | const char *buf, size_t count) | 487 | const char *buf, size_t count) |
| 489 | { | 488 | { |
| 490 | struct ad7877 *ts = dev_get_drvdata(dev); | 489 | struct ad7877 *ts = dev_get_drvdata(dev); |
| 491 | unsigned int val; | 490 | unsigned long val; |
| 492 | int error; | 491 | int error; |
| 493 | 492 | ||
| 494 | error = kstrtouint(buf, 10, &val); | 493 | error = strict_strtoul(buf, 10, &val); |
| 495 | if (error) | 494 | if (error) |
| 496 | return error; | 495 | return error; |
| 497 | 496 | ||
| @@ -518,10 +517,10 @@ static ssize_t ad7877_dac_store(struct device *dev, | |||
| 518 | const char *buf, size_t count) | 517 | const char *buf, size_t count) |
| 519 | { | 518 | { |
| 520 | struct ad7877 *ts = dev_get_drvdata(dev); | 519 | struct ad7877 *ts = dev_get_drvdata(dev); |
| 521 | unsigned int val; | 520 | unsigned long val; |
| 522 | int error; | 521 | int error; |
| 523 | 522 | ||
| 524 | error = kstrtouint(buf, 10, &val); | 523 | error = strict_strtoul(buf, 10, &val); |
| 525 | if (error) | 524 | if (error) |
| 526 | return error; | 525 | return error; |
| 527 | 526 | ||
| @@ -548,10 +547,10 @@ static ssize_t ad7877_gpio3_store(struct device *dev, | |||
| 548 | const char *buf, size_t count) | 547 | const char *buf, size_t count) |
| 549 | { | 548 | { |
| 550 | struct ad7877 *ts = dev_get_drvdata(dev); | 549 | struct ad7877 *ts = dev_get_drvdata(dev); |
| 551 | unsigned int val; | 550 | unsigned long val; |
| 552 | int error; | 551 | int error; |
| 553 | 552 | ||
| 554 | error = kstrtouint(buf, 10, &val); | 553 | error = strict_strtoul(buf, 10, &val); |
| 555 | if (error) | 554 | if (error) |
| 556 | return error; | 555 | return error; |
| 557 | 556 | ||
| @@ -579,10 +578,10 @@ static ssize_t ad7877_gpio4_store(struct device *dev, | |||
| 579 | const char *buf, size_t count) | 578 | const char *buf, size_t count) |
| 580 | { | 579 | { |
| 581 | struct ad7877 *ts = dev_get_drvdata(dev); | 580 | struct ad7877 *ts = dev_get_drvdata(dev); |
| 582 | unsigned int val; | 581 | unsigned long val; |
| 583 | int error; | 582 | int error; |
| 584 | 583 | ||
| 585 | error = kstrtouint(buf, 10, &val); | 584 | error = strict_strtoul(buf, 10, &val); |
| 586 | if (error) | 585 | if (error) |
| 587 | return error; | 586 | return error; |
| 588 | 587 | ||
| @@ -612,10 +611,10 @@ static struct attribute *ad7877_attributes[] = { | |||
| 612 | NULL | 611 | NULL |
| 613 | }; | 612 | }; |
| 614 | 613 | ||
| 615 | static umode_t ad7877_attr_is_visible(struct kobject *kobj, | 614 | static mode_t ad7877_attr_is_visible(struct kobject *kobj, |
| 616 | struct attribute *attr, int n) | 615 | struct attribute *attr, int n) |
| 617 | { | 616 | { |
| 618 | umode_t mode = attr->mode; | 617 | mode_t mode = attr->mode; |
| 619 | 618 | ||
| 620 | if (attr == &dev_attr_aux3.attr) { | 619 | if (attr == &dev_attr_aux3.attr) { |
| 621 | if (gpio3) | 620 | if (gpio3) |
| @@ -682,7 +681,7 @@ static void ad7877_setup_ts_def_msg(struct spi_device *spi, struct ad7877 *ts) | |||
| 682 | } | 681 | } |
| 683 | } | 682 | } |
| 684 | 683 | ||
| 685 | static int ad7877_probe(struct spi_device *spi) | 684 | static int __devinit ad7877_probe(struct spi_device *spi) |
| 686 | { | 685 | { |
| 687 | struct ad7877 *ts; | 686 | struct ad7877 *ts; |
| 688 | struct input_dev *input_dev; | 687 | struct input_dev *input_dev; |
| @@ -810,7 +809,7 @@ err_free_mem: | |||
| 810 | return err; | 809 | return err; |
| 811 | } | 810 | } |
| 812 | 811 | ||
| 813 | static int ad7877_remove(struct spi_device *spi) | 812 | static int __devexit ad7877_remove(struct spi_device *spi) |
| 814 | { | 813 | { |
| 815 | struct ad7877 *ts = dev_get_drvdata(&spi->dev); | 814 | struct ad7877 *ts = dev_get_drvdata(&spi->dev); |
| 816 | 815 | ||
| @@ -853,14 +852,25 @@ static SIMPLE_DEV_PM_OPS(ad7877_pm, ad7877_suspend, ad7877_resume); | |||
| 853 | static struct spi_driver ad7877_driver = { | 852 | static struct spi_driver ad7877_driver = { |
| 854 | .driver = { | 853 | .driver = { |
| 855 | .name = "ad7877", | 854 | .name = "ad7877", |
| 855 | .bus = &spi_bus_type, | ||
| 856 | .owner = THIS_MODULE, | 856 | .owner = THIS_MODULE, |
| 857 | .pm = &ad7877_pm, | 857 | .pm = &ad7877_pm, |
| 858 | }, | 858 | }, |
| 859 | .probe = ad7877_probe, | 859 | .probe = ad7877_probe, |
| 860 | .remove = ad7877_remove, | 860 | .remove = __devexit_p(ad7877_remove), |
| 861 | }; | 861 | }; |
| 862 | 862 | ||
| 863 | module_spi_driver(ad7877_driver); | 863 | static int __init ad7877_init(void) |
| 864 | { | ||
| 865 | return spi_register_driver(&ad7877_driver); | ||
| 866 | } | ||
| 867 | module_init(ad7877_init); | ||
| 868 | |||
| 869 | static void __exit ad7877_exit(void) | ||
| 870 | { | ||
| 871 | spi_unregister_driver(&ad7877_driver); | ||
| 872 | } | ||
| 873 | module_exit(ad7877_exit); | ||
| 864 | 874 | ||
| 865 | MODULE_AUTHOR("Michael Hennerich <hennerich@blackfin.uclinux.org>"); | 875 | MODULE_AUTHOR("Michael Hennerich <hennerich@blackfin.uclinux.org>"); |
| 866 | MODULE_DESCRIPTION("AD7877 touchscreen Driver"); | 876 | MODULE_DESCRIPTION("AD7877 touchscreen Driver"); |
diff --git a/drivers/input/touchscreen/ad7879-i2c.c b/drivers/input/touchscreen/ad7879-i2c.c index dcf39077154..4e4e58cec6c 100644 --- a/drivers/input/touchscreen/ad7879-i2c.c +++ b/drivers/input/touchscreen/ad7879-i2c.c | |||
| @@ -16,6 +16,30 @@ | |||
| 16 | 16 | ||
| 17 | #define AD7879_DEVID 0x79 /* AD7879-1/AD7889-1 */ | 17 | #define AD7879_DEVID 0x79 /* AD7879-1/AD7889-1 */ |
| 18 | 18 | ||
| 19 | #ifdef CONFIG_PM | ||
| 20 | static int ad7879_i2c_suspend(struct device *dev) | ||
| 21 | { | ||
| 22 | struct i2c_client *client = to_i2c_client(dev); | ||
| 23 | struct ad7879 *ts = i2c_get_clientdata(client); | ||
| 24 | |||
| 25 | ad7879_suspend(ts); | ||
| 26 | |||
| 27 | return 0; | ||
| 28 | } | ||
| 29 | |||
| 30 | static int ad7879_i2c_resume(struct device *dev) | ||
| 31 | { | ||
| 32 | struct i2c_client *client = to_i2c_client(dev); | ||
| 33 | struct ad7879 *ts = i2c_get_clientdata(client); | ||
| 34 | |||
| 35 | ad7879_resume(ts); | ||
| 36 | |||
| 37 | return 0; | ||
| 38 | } | ||
| 39 | |||
| 40 | static SIMPLE_DEV_PM_OPS(ad7879_i2c_pm, ad7879_i2c_suspend, ad7879_i2c_resume); | ||
| 41 | #endif | ||
| 42 | |||
| 19 | /* All registers are word-sized. | 43 | /* All registers are word-sized. |
| 20 | * AD7879 uses a high-byte first convention. | 44 | * AD7879 uses a high-byte first convention. |
| 21 | */ | 45 | */ |
| @@ -23,7 +47,7 @@ static int ad7879_i2c_read(struct device *dev, u8 reg) | |||
| 23 | { | 47 | { |
| 24 | struct i2c_client *client = to_i2c_client(dev); | 48 | struct i2c_client *client = to_i2c_client(dev); |
| 25 | 49 | ||
| 26 | return i2c_smbus_read_word_swapped(client, reg); | 50 | return swab16(i2c_smbus_read_word_data(client, reg)); |
| 27 | } | 51 | } |
| 28 | 52 | ||
| 29 | static int ad7879_i2c_multi_read(struct device *dev, | 53 | static int ad7879_i2c_multi_read(struct device *dev, |
| @@ -44,7 +68,7 @@ static int ad7879_i2c_write(struct device *dev, u8 reg, u16 val) | |||
| 44 | { | 68 | { |
| 45 | struct i2c_client *client = to_i2c_client(dev); | 69 | struct i2c_client *client = to_i2c_client(dev); |
| 46 | 70 | ||
| 47 | return i2c_smbus_write_word_swapped(client, reg, val); | 71 | return i2c_smbus_write_word_data(client, reg, swab16(val)); |
| 48 | } | 72 | } |
| 49 | 73 | ||
| 50 | static const struct ad7879_bus_ops ad7879_i2c_bus_ops = { | 74 | static const struct ad7879_bus_ops ad7879_i2c_bus_ops = { |
| @@ -54,7 +78,7 @@ static const struct ad7879_bus_ops ad7879_i2c_bus_ops = { | |||
| 54 | .write = ad7879_i2c_write, | 78 | .write = ad7879_i2c_write, |
| 55 | }; | 79 | }; |
| 56 | 80 | ||
| 57 | static int ad7879_i2c_probe(struct i2c_client *client, | 81 | static int __devinit ad7879_i2c_probe(struct i2c_client *client, |
| 58 | const struct i2c_device_id *id) | 82 | const struct i2c_device_id *id) |
| 59 | { | 83 | { |
| 60 | struct ad7879 *ts; | 84 | struct ad7879 *ts; |
| @@ -75,7 +99,7 @@ static int ad7879_i2c_probe(struct i2c_client *client, | |||
| 75 | return 0; | 99 | return 0; |
| 76 | } | 100 | } |
| 77 | 101 | ||
| 78 | static int ad7879_i2c_remove(struct i2c_client *client) | 102 | static int __devexit ad7879_i2c_remove(struct i2c_client *client) |
| 79 | { | 103 | { |
| 80 | struct ad7879 *ts = i2c_get_clientdata(client); | 104 | struct ad7879 *ts = i2c_get_clientdata(client); |
| 81 | 105 | ||
| @@ -95,15 +119,28 @@ static struct i2c_driver ad7879_i2c_driver = { | |||
| 95 | .driver = { | 119 | .driver = { |
| 96 | .name = "ad7879", | 120 | .name = "ad7879", |
| 97 | .owner = THIS_MODULE, | 121 | .owner = THIS_MODULE, |
| 98 | .pm = &ad7879_pm_ops, | 122 | #ifdef CONFIG_PM |
| 123 | .pm = &ad7879_i2c_pm, | ||
| 124 | #endif | ||
| 99 | }, | 125 | }, |
| 100 | .probe = ad7879_i2c_probe, | 126 | .probe = ad7879_i2c_probe, |
| 101 | .remove = ad7879_i2c_remove, | 127 | .remove = __devexit_p(ad7879_i2c_remove), |
| 102 | .id_table = ad7879_id, | 128 | .id_table = ad7879_id, |
| 103 | }; | 129 | }; |
| 104 | 130 | ||
| 105 | module_i2c_driver(ad7879_i2c_driver); | 131 | static int __init ad7879_i2c_init(void) |
| 132 | { | ||
| 133 | return i2c_add_driver(&ad7879_i2c_driver); | ||
| 134 | } | ||
| 135 | module_init(ad7879_i2c_init); | ||
| 136 | |||
| 137 | static void __exit ad7879_i2c_exit(void) | ||
| 138 | { | ||
| 139 | i2c_del_driver(&ad7879_i2c_driver); | ||
| 140 | } | ||
| 141 | module_exit(ad7879_i2c_exit); | ||
| 106 | 142 | ||
| 107 | MODULE_AUTHOR("Michael Hennerich <hennerich@blackfin.uclinux.org>"); | 143 | MODULE_AUTHOR("Michael Hennerich <hennerich@blackfin.uclinux.org>"); |
| 108 | MODULE_DESCRIPTION("AD7879(-1) touchscreen I2C bus driver"); | 144 | MODULE_DESCRIPTION("AD7879(-1) touchscreen I2C bus driver"); |
| 109 | MODULE_LICENSE("GPL"); | 145 | MODULE_LICENSE("GPL"); |
| 146 | MODULE_ALIAS("i2c:ad7879"); | ||
diff --git a/drivers/input/touchscreen/ad7879-spi.c b/drivers/input/touchscreen/ad7879-spi.c index 606da5bd611..ddf732f3caf 100644 --- a/drivers/input/touchscreen/ad7879-spi.c +++ b/drivers/input/touchscreen/ad7879-spi.c | |||
| @@ -9,7 +9,6 @@ | |||
| 9 | #include <linux/input.h> /* BUS_SPI */ | 9 | #include <linux/input.h> /* BUS_SPI */ |
| 10 | #include <linux/pm.h> | 10 | #include <linux/pm.h> |
| 11 | #include <linux/spi/spi.h> | 11 | #include <linux/spi/spi.h> |
| 12 | #include <linux/module.h> | ||
| 13 | 12 | ||
| 14 | #include "ad7879.h" | 13 | #include "ad7879.h" |
| 15 | 14 | ||
| @@ -22,6 +21,30 @@ | |||
| 22 | #define AD7879_WRITECMD(reg) (AD7879_CMD(reg)) | 21 | #define AD7879_WRITECMD(reg) (AD7879_CMD(reg)) |
| 23 | #define AD7879_READCMD(reg) (AD7879_CMD(reg) | AD7879_CMD_READ) | 22 | #define AD7879_READCMD(reg) (AD7879_CMD(reg) | AD7879_CMD_READ) |
| 24 | 23 | ||
| 24 | #ifdef CONFIG_PM_SLEEP | ||
| 25 | static int ad7879_spi_suspend(struct device *dev) | ||
| 26 | { | ||
| 27 | struct spi_device *spi = to_spi_device(dev); | ||
| 28 | struct ad7879 *ts = spi_get_drvdata(spi); | ||
| 29 | |||
| 30 | ad7879_suspend(ts); | ||
| 31 | |||
| 32 | return 0; | ||
| 33 | } | ||
| 34 | |||
| 35 | static int ad7879_spi_resume(struct device *dev) | ||
| 36 | { | ||
| 37 | struct spi_device *spi = to_spi_device(dev); | ||
| 38 | struct ad7879 *ts = spi_get_drvdata(spi); | ||
| 39 | |||
| 40 | ad7879_resume(ts); | ||
| 41 | |||
| 42 | return 0; | ||
| 43 | } | ||
| 44 | #endif | ||
| 45 | |||
| 46 | static SIMPLE_DEV_PM_OPS(ad7879_spi_pm, ad7879_spi_suspend, ad7879_spi_resume); | ||
| 47 | |||
| 25 | /* | 48 | /* |
| 26 | * ad7879_read/write are only used for initial setup and for sysfs controls. | 49 | * ad7879_read/write are only used for initial setup and for sysfs controls. |
| 27 | * The main traffic is done in ad7879_collect(). | 50 | * The main traffic is done in ad7879_collect(). |
| @@ -110,7 +133,7 @@ static const struct ad7879_bus_ops ad7879_spi_bus_ops = { | |||
| 110 | .write = ad7879_spi_write, | 133 | .write = ad7879_spi_write, |
| 111 | }; | 134 | }; |
| 112 | 135 | ||
| 113 | static int ad7879_spi_probe(struct spi_device *spi) | 136 | static int __devinit ad7879_spi_probe(struct spi_device *spi) |
| 114 | { | 137 | { |
| 115 | struct ad7879 *ts; | 138 | struct ad7879 *ts; |
| 116 | int err; | 139 | int err; |
| @@ -137,7 +160,7 @@ static int ad7879_spi_probe(struct spi_device *spi) | |||
| 137 | return 0; | 160 | return 0; |
| 138 | } | 161 | } |
| 139 | 162 | ||
| 140 | static int ad7879_spi_remove(struct spi_device *spi) | 163 | static int __devexit ad7879_spi_remove(struct spi_device *spi) |
| 141 | { | 164 | { |
| 142 | struct ad7879 *ts = spi_get_drvdata(spi); | 165 | struct ad7879 *ts = spi_get_drvdata(spi); |
| 143 | 166 | ||
| @@ -150,14 +173,25 @@ static int ad7879_spi_remove(struct spi_device *spi) | |||
| 150 | static struct spi_driver ad7879_spi_driver = { | 173 | static struct spi_driver ad7879_spi_driver = { |
| 151 | .driver = { | 174 | .driver = { |
| 152 | .name = "ad7879", | 175 | .name = "ad7879", |
| 176 | .bus = &spi_bus_type, | ||
| 153 | .owner = THIS_MODULE, | 177 | .owner = THIS_MODULE, |
| 154 | .pm = &ad7879_pm_ops, | 178 | .pm = &ad7879_spi_pm, |
| 155 | }, | 179 | }, |
| 156 | .probe = ad7879_spi_probe, | 180 | .probe = ad7879_spi_probe, |
| 157 | .remove = ad7879_spi_remove, | 181 | .remove = __devexit_p(ad7879_spi_remove), |
| 158 | }; | 182 | }; |
| 159 | 183 | ||
| 160 | module_spi_driver(ad7879_spi_driver); | 184 | static int __init ad7879_spi_init(void) |
| 185 | { | ||
| 186 | return spi_register_driver(&ad7879_spi_driver); | ||
| 187 | } | ||
| 188 | module_init(ad7879_spi_init); | ||
| 189 | |||
| 190 | static void __exit ad7879_spi_exit(void) | ||
| 191 | { | ||
| 192 | spi_unregister_driver(&ad7879_spi_driver); | ||
| 193 | } | ||
| 194 | module_exit(ad7879_spi_exit); | ||
| 161 | 195 | ||
| 162 | MODULE_AUTHOR("Michael Hennerich <hennerich@blackfin.uclinux.org>"); | 196 | MODULE_AUTHOR("Michael Hennerich <hennerich@blackfin.uclinux.org>"); |
| 163 | MODULE_DESCRIPTION("AD7879(-1) touchscreen SPI bus driver"); | 197 | MODULE_DESCRIPTION("AD7879(-1) touchscreen SPI bus driver"); |
diff --git a/drivers/input/touchscreen/ad7879.c b/drivers/input/touchscreen/ad7879.c index facd3057b62..131f9d1c921 100644 --- a/drivers/input/touchscreen/ad7879.c +++ b/drivers/input/touchscreen/ad7879.c | |||
| @@ -33,7 +33,6 @@ | |||
| 33 | #include <linux/gpio.h> | 33 | #include <linux/gpio.h> |
| 34 | 34 | ||
| 35 | #include <linux/spi/ad7879.h> | 35 | #include <linux/spi/ad7879.h> |
| 36 | #include <linux/module.h> | ||
| 37 | #include "ad7879.h" | 36 | #include "ad7879.h" |
| 38 | 37 | ||
| 39 | #define AD7879_REG_ZEROS 0 | 38 | #define AD7879_REG_ZEROS 0 |
| @@ -118,7 +117,6 @@ struct ad7879 { | |||
| 118 | unsigned int irq; | 117 | unsigned int irq; |
| 119 | bool disabled; /* P: input->mutex */ | 118 | bool disabled; /* P: input->mutex */ |
| 120 | bool suspended; /* P: input->mutex */ | 119 | bool suspended; /* P: input->mutex */ |
| 121 | bool swap_xy; | ||
| 122 | u16 conversion_data[AD7879_NR_SENSE]; | 120 | u16 conversion_data[AD7879_NR_SENSE]; |
| 123 | char phys[32]; | 121 | char phys[32]; |
| 124 | u8 first_conversion_delay; | 122 | u8 first_conversion_delay; |
| @@ -162,9 +160,6 @@ static int ad7879_report(struct ad7879 *ts) | |||
| 162 | z1 = ts->conversion_data[AD7879_SEQ_Z1] & MAX_12BIT; | 160 | z1 = ts->conversion_data[AD7879_SEQ_Z1] & MAX_12BIT; |
| 163 | z2 = ts->conversion_data[AD7879_SEQ_Z2] & MAX_12BIT; | 161 | z2 = ts->conversion_data[AD7879_SEQ_Z2] & MAX_12BIT; |
| 164 | 162 | ||
| 165 | if (ts->swap_xy) | ||
| 166 | swap(x, y); | ||
| 167 | |||
| 168 | /* | 163 | /* |
| 169 | * The samples processed here are already preprocessed by the AD7879. | 164 | * The samples processed here are already preprocessed by the AD7879. |
| 170 | * The preprocessing function consists of a median and an averaging | 165 | * The preprocessing function consists of a median and an averaging |
| @@ -285,11 +280,8 @@ static void ad7879_close(struct input_dev* input) | |||
| 285 | __ad7879_disable(ts); | 280 | __ad7879_disable(ts); |
| 286 | } | 281 | } |
| 287 | 282 | ||
| 288 | #ifdef CONFIG_PM_SLEEP | 283 | void ad7879_suspend(struct ad7879 *ts) |
| 289 | static int ad7879_suspend(struct device *dev) | ||
| 290 | { | 284 | { |
| 291 | struct ad7879 *ts = dev_get_drvdata(dev); | ||
| 292 | |||
| 293 | mutex_lock(&ts->input->mutex); | 285 | mutex_lock(&ts->input->mutex); |
| 294 | 286 | ||
| 295 | if (!ts->suspended && !ts->disabled && ts->input->users) | 287 | if (!ts->suspended && !ts->disabled && ts->input->users) |
| @@ -298,14 +290,11 @@ static int ad7879_suspend(struct device *dev) | |||
| 298 | ts->suspended = true; | 290 | ts->suspended = true; |
| 299 | 291 | ||
| 300 | mutex_unlock(&ts->input->mutex); | 292 | mutex_unlock(&ts->input->mutex); |
| 301 | |||
| 302 | return 0; | ||
| 303 | } | 293 | } |
| 294 | EXPORT_SYMBOL(ad7879_suspend); | ||
| 304 | 295 | ||
| 305 | static int ad7879_resume(struct device *dev) | 296 | void ad7879_resume(struct ad7879 *ts) |
| 306 | { | 297 | { |
| 307 | struct ad7879 *ts = dev_get_drvdata(dev); | ||
| 308 | |||
| 309 | mutex_lock(&ts->input->mutex); | 298 | mutex_lock(&ts->input->mutex); |
| 310 | 299 | ||
| 311 | if (ts->suspended && !ts->disabled && ts->input->users) | 300 | if (ts->suspended && !ts->disabled && ts->input->users) |
| @@ -314,13 +303,8 @@ static int ad7879_resume(struct device *dev) | |||
| 314 | ts->suspended = false; | 303 | ts->suspended = false; |
| 315 | 304 | ||
| 316 | mutex_unlock(&ts->input->mutex); | 305 | mutex_unlock(&ts->input->mutex); |
| 317 | |||
| 318 | return 0; | ||
| 319 | } | 306 | } |
| 320 | #endif | 307 | EXPORT_SYMBOL(ad7879_resume); |
| 321 | |||
| 322 | SIMPLE_DEV_PM_OPS(ad7879_pm_ops, ad7879_suspend, ad7879_resume); | ||
| 323 | EXPORT_SYMBOL(ad7879_pm_ops); | ||
| 324 | 308 | ||
| 325 | static void ad7879_toggle(struct ad7879 *ts, bool disable) | 309 | static void ad7879_toggle(struct ad7879 *ts, bool disable) |
| 326 | { | 310 | { |
| @@ -355,10 +339,10 @@ static ssize_t ad7879_disable_store(struct device *dev, | |||
| 355 | const char *buf, size_t count) | 339 | const char *buf, size_t count) |
| 356 | { | 340 | { |
| 357 | struct ad7879 *ts = dev_get_drvdata(dev); | 341 | struct ad7879 *ts = dev_get_drvdata(dev); |
| 358 | unsigned int val; | 342 | unsigned long val; |
| 359 | int error; | 343 | int error; |
| 360 | 344 | ||
| 361 | error = kstrtouint(buf, 10, &val); | 345 | error = strict_strtoul(buf, 10, &val); |
| 362 | if (error) | 346 | if (error) |
| 363 | return error; | 347 | return error; |
| 364 | 348 | ||
| @@ -524,7 +508,6 @@ struct ad7879 *ad7879_probe(struct device *dev, u8 devid, unsigned int irq, | |||
| 524 | ts->dev = dev; | 508 | ts->dev = dev; |
| 525 | ts->input = input_dev; | 509 | ts->input = input_dev; |
| 526 | ts->irq = irq; | 510 | ts->irq = irq; |
| 527 | ts->swap_xy = pdata->swap_xy; | ||
| 528 | 511 | ||
| 529 | setup_timer(&ts->timer, ad7879_timer, (unsigned long) ts); | 512 | setup_timer(&ts->timer, ad7879_timer, (unsigned long) ts); |
| 530 | 513 | ||
| @@ -602,7 +585,7 @@ struct ad7879 *ad7879_probe(struct device *dev, u8 devid, unsigned int irq, | |||
| 602 | AD7879_TMR(ts->pen_down_acc_interval); | 585 | AD7879_TMR(ts->pen_down_acc_interval); |
| 603 | 586 | ||
| 604 | err = request_threaded_irq(ts->irq, NULL, ad7879_irq, | 587 | err = request_threaded_irq(ts->irq, NULL, ad7879_irq, |
| 605 | IRQF_TRIGGER_FALLING | IRQF_ONESHOT, | 588 | IRQF_TRIGGER_FALLING, |
| 606 | dev_name(dev), ts); | 589 | dev_name(dev), ts); |
| 607 | if (err) { | 590 | if (err) { |
| 608 | dev_err(dev, "irq %d busy?\n", ts->irq); | 591 | dev_err(dev, "irq %d busy?\n", ts->irq); |
diff --git a/drivers/input/touchscreen/ad7879.h b/drivers/input/touchscreen/ad7879.h index 6fd13c48d37..6b45a27236c 100644 --- a/drivers/input/touchscreen/ad7879.h +++ b/drivers/input/touchscreen/ad7879.h | |||
| @@ -21,8 +21,8 @@ struct ad7879_bus_ops { | |||
| 21 | int (*write)(struct device *dev, u8 reg, u16 val); | 21 | int (*write)(struct device *dev, u8 reg, u16 val); |
| 22 | }; | 22 | }; |
| 23 | 23 | ||
| 24 | extern const struct dev_pm_ops ad7879_pm_ops; | 24 | void ad7879_suspend(struct ad7879 *); |
| 25 | 25 | void ad7879_resume(struct ad7879 *); | |
| 26 | struct ad7879 *ad7879_probe(struct device *dev, u8 devid, unsigned irq, | 26 | struct ad7879 *ad7879_probe(struct device *dev, u8 devid, unsigned irq, |
| 27 | const struct ad7879_bus_ops *bops); | 27 | const struct ad7879_bus_ops *bops); |
| 28 | void ad7879_remove(struct ad7879 *); | 28 | void ad7879_remove(struct ad7879 *); |
diff --git a/drivers/input/touchscreen/ads7846.c b/drivers/input/touchscreen/ads7846.c index 4f702b3ec1a..d507b9b6780 100644 --- a/drivers/input/touchscreen/ads7846.c +++ b/drivers/input/touchscreen/ads7846.c | |||
| @@ -31,7 +31,6 @@ | |||
| 31 | #include <linux/spi/spi.h> | 31 | #include <linux/spi/spi.h> |
| 32 | #include <linux/spi/ads7846.h> | 32 | #include <linux/spi/ads7846.h> |
| 33 | #include <linux/regulator/consumer.h> | 33 | #include <linux/regulator/consumer.h> |
| 34 | #include <linux/module.h> | ||
| 35 | #include <asm/irq.h> | 34 | #include <asm/irq.h> |
| 36 | 35 | ||
| 37 | /* | 36 | /* |
| @@ -602,12 +601,10 @@ static ssize_t ads7846_disable_store(struct device *dev, | |||
| 602 | const char *buf, size_t count) | 601 | const char *buf, size_t count) |
| 603 | { | 602 | { |
| 604 | struct ads7846 *ts = dev_get_drvdata(dev); | 603 | struct ads7846 *ts = dev_get_drvdata(dev); |
| 605 | unsigned int i; | 604 | unsigned long i; |
| 606 | int err; | ||
| 607 | 605 | ||
| 608 | err = kstrtouint(buf, 10, &i); | 606 | if (strict_strtoul(buf, 10, &i)) |
| 609 | if (err) | 607 | return -EINVAL; |
| 610 | return err; | ||
| 611 | 608 | ||
| 612 | if (i) | 609 | if (i) |
| 613 | ads7846_disable(ts); | 610 | ads7846_disable(ts); |
| @@ -955,8 +952,7 @@ static int ads7846_resume(struct device *dev) | |||
| 955 | 952 | ||
| 956 | static SIMPLE_DEV_PM_OPS(ads7846_pm, ads7846_suspend, ads7846_resume); | 953 | static SIMPLE_DEV_PM_OPS(ads7846_pm, ads7846_suspend, ads7846_resume); |
| 957 | 954 | ||
| 958 | static int ads7846_setup_pendown(struct spi_device *spi, | 955 | static int __devinit ads7846_setup_pendown(struct spi_device *spi, struct ads7846 *ts) |
| 959 | struct ads7846 *ts) | ||
| 960 | { | 956 | { |
| 961 | struct ads7846_platform_data *pdata = spi->dev.platform_data; | 957 | struct ads7846_platform_data *pdata = spi->dev.platform_data; |
| 962 | int err; | 958 | int err; |
| @@ -982,9 +978,6 @@ static int ads7846_setup_pendown(struct spi_device *spi, | |||
| 982 | 978 | ||
| 983 | ts->gpio_pendown = pdata->gpio_pendown; | 979 | ts->gpio_pendown = pdata->gpio_pendown; |
| 984 | 980 | ||
| 985 | if (pdata->gpio_pendown_debounce) | ||
| 986 | gpio_set_debounce(pdata->gpio_pendown, | ||
| 987 | pdata->gpio_pendown_debounce); | ||
| 988 | } else { | 981 | } else { |
| 989 | dev_err(&spi->dev, "no get_pendown_state nor gpio_pendown?\n"); | 982 | dev_err(&spi->dev, "no get_pendown_state nor gpio_pendown?\n"); |
| 990 | return -EINVAL; | 983 | return -EINVAL; |
| @@ -997,7 +990,7 @@ static int ads7846_setup_pendown(struct spi_device *spi, | |||
| 997 | * Set up the transfers to read touchscreen state; this assumes we | 990 | * Set up the transfers to read touchscreen state; this assumes we |
| 998 | * use formula #2 for pressure, not #3. | 991 | * use formula #2 for pressure, not #3. |
| 999 | */ | 992 | */ |
| 1000 | static void ads7846_setup_spi_msg(struct ads7846 *ts, | 993 | static void __devinit ads7846_setup_spi_msg(struct ads7846 *ts, |
| 1001 | const struct ads7846_platform_data *pdata) | 994 | const struct ads7846_platform_data *pdata) |
| 1002 | { | 995 | { |
| 1003 | struct spi_message *m = &ts->msg[0]; | 996 | struct spi_message *m = &ts->msg[0]; |
| @@ -1196,7 +1189,7 @@ static void ads7846_setup_spi_msg(struct ads7846 *ts, | |||
| 1196 | spi_message_add_tail(x, m); | 1189 | spi_message_add_tail(x, m); |
| 1197 | } | 1190 | } |
| 1198 | 1191 | ||
| 1199 | static int ads7846_probe(struct spi_device *spi) | 1192 | static int __devinit ads7846_probe(struct spi_device *spi) |
| 1200 | { | 1193 | { |
| 1201 | struct ads7846 *ts; | 1194 | struct ads7846 *ts; |
| 1202 | struct ads7846_packet *packet; | 1195 | struct ads7846_packet *packet; |
| @@ -1390,7 +1383,7 @@ static int ads7846_probe(struct spi_device *spi) | |||
| 1390 | return err; | 1383 | return err; |
| 1391 | } | 1384 | } |
| 1392 | 1385 | ||
| 1393 | static int ads7846_remove(struct spi_device *spi) | 1386 | static int __devexit ads7846_remove(struct spi_device *spi) |
| 1394 | { | 1387 | { |
| 1395 | struct ads7846 *ts = dev_get_drvdata(&spi->dev); | 1388 | struct ads7846 *ts = dev_get_drvdata(&spi->dev); |
| 1396 | 1389 | ||
| @@ -1430,14 +1423,25 @@ static int ads7846_remove(struct spi_device *spi) | |||
| 1430 | static struct spi_driver ads7846_driver = { | 1423 | static struct spi_driver ads7846_driver = { |
| 1431 | .driver = { | 1424 | .driver = { |
| 1432 | .name = "ads7846", | 1425 | .name = "ads7846", |
| 1426 | .bus = &spi_bus_type, | ||
| 1433 | .owner = THIS_MODULE, | 1427 | .owner = THIS_MODULE, |
| 1434 | .pm = &ads7846_pm, | 1428 | .pm = &ads7846_pm, |
| 1435 | }, | 1429 | }, |
| 1436 | .probe = ads7846_probe, | 1430 | .probe = ads7846_probe, |
| 1437 | .remove = ads7846_remove, | 1431 | .remove = __devexit_p(ads7846_remove), |
| 1438 | }; | 1432 | }; |
| 1439 | 1433 | ||
| 1440 | module_spi_driver(ads7846_driver); | 1434 | static int __init ads7846_init(void) |
| 1435 | { | ||
| 1436 | return spi_register_driver(&ads7846_driver); | ||
| 1437 | } | ||
| 1438 | module_init(ads7846_init); | ||
| 1439 | |||
| 1440 | static void __exit ads7846_exit(void) | ||
| 1441 | { | ||
| 1442 | spi_unregister_driver(&ads7846_driver); | ||
| 1443 | } | ||
| 1444 | module_exit(ads7846_exit); | ||
| 1441 | 1445 | ||
| 1442 | MODULE_DESCRIPTION("ADS7846 TouchScreen Driver"); | 1446 | MODULE_DESCRIPTION("ADS7846 TouchScreen Driver"); |
| 1443 | MODULE_LICENSE("GPL"); | 1447 | MODULE_LICENSE("GPL"); |
diff --git a/drivers/input/touchscreen/atmel-wm97xx.c b/drivers/input/touchscreen/atmel-wm97xx.c index c5c2dbb9386..8034cbb20f7 100644 --- a/drivers/input/touchscreen/atmel-wm97xx.c +++ b/drivers/input/touchscreen/atmel-wm97xx.c | |||
| @@ -392,10 +392,9 @@ static int __exit atmel_wm97xx_remove(struct platform_device *pdev) | |||
| 392 | return 0; | 392 | return 0; |
| 393 | } | 393 | } |
| 394 | 394 | ||
| 395 | #ifdef CONFIG_PM_SLEEP | 395 | #ifdef CONFIG_PM |
| 396 | static int atmel_wm97xx_suspend(struct *dev) | 396 | static int atmel_wm97xx_suspend(struct platform_device *pdev, pm_message_t msg) |
| 397 | { | 397 | { |
| 398 | struct platform_device *pdev = to_platform_device(dev); | ||
| 399 | struct atmel_wm97xx *atmel_wm97xx = platform_get_drvdata(pdev); | 398 | struct atmel_wm97xx *atmel_wm97xx = platform_get_drvdata(pdev); |
| 400 | 399 | ||
| 401 | ac97c_writel(atmel_wm97xx, IDR, AC97C_INT_CBEVT); | 400 | ac97c_writel(atmel_wm97xx, IDR, AC97C_INT_CBEVT); |
| @@ -405,9 +404,8 @@ static int atmel_wm97xx_suspend(struct *dev) | |||
| 405 | return 0; | 404 | return 0; |
| 406 | } | 405 | } |
| 407 | 406 | ||
| 408 | static int atmel_wm97xx_resume(struct device *dev) | 407 | static int atmel_wm97xx_resume(struct platform_device *pdev) |
| 409 | { | 408 | { |
| 410 | struct platform_device *pdev = to_platform_device(dev); | ||
| 411 | struct atmel_wm97xx *atmel_wm97xx = platform_get_drvdata(pdev); | 409 | struct atmel_wm97xx *atmel_wm97xx = platform_get_drvdata(pdev); |
| 412 | struct wm97xx *wm = atmel_wm97xx->wm; | 410 | struct wm97xx *wm = atmel_wm97xx->wm; |
| 413 | 411 | ||
| @@ -418,18 +416,18 @@ static int atmel_wm97xx_resume(struct device *dev) | |||
| 418 | 416 | ||
| 419 | return 0; | 417 | return 0; |
| 420 | } | 418 | } |
| 419 | #else | ||
| 420 | #define atmel_wm97xx_suspend NULL | ||
| 421 | #define atmel_wm97xx_resume NULL | ||
| 421 | #endif | 422 | #endif |
| 422 | 423 | ||
| 423 | static SIMPLE_DEV_PM_OPS(atmel_wm97xx_pm_ops, | ||
| 424 | atmel_wm97xx_suspend, atmel_wm97xx_resume); | ||
| 425 | |||
| 426 | static struct platform_driver atmel_wm97xx_driver = { | 424 | static struct platform_driver atmel_wm97xx_driver = { |
| 427 | .remove = __exit_p(atmel_wm97xx_remove), | 425 | .remove = __exit_p(atmel_wm97xx_remove), |
| 428 | .driver = { | 426 | .driver = { |
| 429 | .name = "wm97xx-touch", | 427 | .name = "wm97xx-touch", |
| 430 | .owner = THIS_MODULE, | ||
| 431 | .pm = &atmel_wm97xx_pm_ops, | ||
| 432 | }, | 428 | }, |
| 429 | .suspend = atmel_wm97xx_suspend, | ||
| 430 | .resume = atmel_wm97xx_resume, | ||
| 433 | }; | 431 | }; |
| 434 | 432 | ||
| 435 | static int __init atmel_wm97xx_init(void) | 433 | static int __init atmel_wm97xx_init(void) |
diff --git a/drivers/input/touchscreen/atmel_mxt_ts.c b/drivers/input/touchscreen/atmel_mxt_ts.c index d04f810cb1d..ad21ef9c010 100644 --- a/drivers/input/touchscreen/atmel_mxt_ts.c +++ b/drivers/input/touchscreen/atmel_mxt_ts.c | |||
| @@ -2,6 +2,8 @@ | |||
| 2 | * Atmel maXTouch Touchscreen driver | 2 | * Atmel maXTouch Touchscreen driver |
| 3 | * | 3 | * |
| 4 | * Copyright (C) 2010 Samsung Electronics Co.Ltd | 4 | * Copyright (C) 2010 Samsung Electronics Co.Ltd |
| 5 | * Copyright (C) 2011 Atmel Corporation | ||
| 6 | * Copyright (C) 2011 NVIDIA Corporation | ||
| 5 | * Author: Joonyoung Shim <jy0922.shim@samsung.com> | 7 | * Author: Joonyoung Shim <jy0922.shim@samsung.com> |
| 6 | * | 8 | * |
| 7 | * This program is free software; you can redistribute it and/or modify it | 9 | * This program is free software; you can redistribute it and/or modify it |
| @@ -17,9 +19,17 @@ | |||
| 17 | #include <linux/firmware.h> | 19 | #include <linux/firmware.h> |
| 18 | #include <linux/i2c.h> | 20 | #include <linux/i2c.h> |
| 19 | #include <linux/i2c/atmel_mxt_ts.h> | 21 | #include <linux/i2c/atmel_mxt_ts.h> |
| 20 | #include <linux/input/mt.h> | 22 | #include <linux/input.h> |
| 21 | #include <linux/interrupt.h> | 23 | #include <linux/interrupt.h> |
| 22 | #include <linux/slab.h> | 24 | #include <linux/slab.h> |
| 25 | #if defined(CONFIG_HAS_EARLYSUSPEND) | ||
| 26 | #include <linux/earlysuspend.h> | ||
| 27 | #endif | ||
| 28 | |||
| 29 | /* Family ID */ | ||
| 30 | #define MXT224_ID 0x80 | ||
| 31 | #define MXT768E_ID 0xA1 | ||
| 32 | #define MXT1386_ID 0xA0 | ||
| 23 | 33 | ||
| 24 | /* Version */ | 34 | /* Version */ |
| 25 | #define MXT_VER_20 20 | 35 | #define MXT_VER_20 20 |
| @@ -36,7 +46,6 @@ | |||
| 36 | #define MXT_FW_NAME "maxtouch.fw" | 46 | #define MXT_FW_NAME "maxtouch.fw" |
| 37 | 47 | ||
| 38 | /* Registers */ | 48 | /* Registers */ |
| 39 | #define MXT_INFO 0x00 | ||
| 40 | #define MXT_FAMILY_ID 0x00 | 49 | #define MXT_FAMILY_ID 0x00 |
| 41 | #define MXT_VARIANT_ID 0x01 | 50 | #define MXT_VARIANT_ID 0x01 |
| 42 | #define MXT_VERSION 0x02 | 51 | #define MXT_VERSION 0x02 |
| @@ -173,14 +182,37 @@ | |||
| 173 | #define MXT_VOLTAGE_DEFAULT 2700000 | 182 | #define MXT_VOLTAGE_DEFAULT 2700000 |
| 174 | #define MXT_VOLTAGE_STEP 10000 | 183 | #define MXT_VOLTAGE_STEP 10000 |
| 175 | 184 | ||
| 185 | /* Defines for Suspend/Resume */ | ||
| 186 | #define MXT_SUSPEND_STATIC 0 | ||
| 187 | #define MXT_SUSPEND_DYNAMIC 1 | ||
| 188 | #define MXT_T7_IDLEACQ_DISABLE 0 | ||
| 189 | #define MXT_T7_ACTVACQ_DISABLE 0 | ||
| 190 | #define MXT_T7_ACTV2IDLE_DISABLE 0 | ||
| 191 | #define MXT_T9_DISABLE 0 | ||
| 192 | #define MXT_T9_ENABLE 0x83 | ||
| 193 | #define MXT_T22_DISABLE 0 | ||
| 194 | |||
| 176 | /* Define for MXT_GEN_COMMAND_T6 */ | 195 | /* Define for MXT_GEN_COMMAND_T6 */ |
| 177 | #define MXT_BOOT_VALUE 0xa5 | 196 | #define MXT_BOOT_VALUE 0xa5 |
| 178 | #define MXT_BACKUP_VALUE 0x55 | 197 | #define MXT_BACKUP_VALUE 0x55 |
| 179 | #define MXT_BACKUP_TIME 25 /* msec */ | 198 | #define MXT_BACKUP_TIME 200 /* msec */ |
| 180 | #define MXT_RESET_TIME 65 /* msec */ | 199 | #define MXT224_RESET_TIME 65 /* msec */ |
| 200 | #define MXT768E_RESET_TIME 250 /* msec */ | ||
| 201 | #define MXT1386_RESET_TIME 200 /* msec */ | ||
| 202 | #define MXT_RESET_TIME 200 /* msec */ | ||
| 203 | #define MXT_RESET_NOCHGREAD 400 /* msec */ | ||
| 204 | |||
| 205 | #define MXT_WAKEUP_TIME 25 /* msec */ | ||
| 181 | 206 | ||
| 182 | #define MXT_FWRESET_TIME 175 /* msec */ | 207 | #define MXT_FWRESET_TIME 175 /* msec */ |
| 183 | 208 | ||
| 209 | /* Defines for MXT_SLOWSCAN_EXTENSIONS */ | ||
| 210 | #define SLOSCAN_DISABLE 0 /* Disable slow scan */ | ||
| 211 | #define SLOSCAN_ENABLE 1 /* Enable slow scan */ | ||
| 212 | #define SLOSCAN_SET_ACTVACQINT 2 /* Set ACTV scan rate */ | ||
| 213 | #define SLOSCAN_SET_IDLEACQINT 3 /* Set IDLE scan rate */ | ||
| 214 | #define SLOSCAN_SET_ACTV2IDLETO 4 /* Set the ACTIVE to IDLE TimeOut */ | ||
| 215 | |||
| 184 | /* Command to unlock bootloader */ | 216 | /* Command to unlock bootloader */ |
| 185 | #define MXT_UNLOCK_CMD_MSB 0xaa | 217 | #define MXT_UNLOCK_CMD_MSB 0xaa |
| 186 | #define MXT_UNLOCK_CMD_LSB 0xdc | 218 | #define MXT_UNLOCK_CMD_LSB 0xdc |
| @@ -195,7 +227,6 @@ | |||
| 195 | #define MXT_BOOT_STATUS_MASK 0x3f | 227 | #define MXT_BOOT_STATUS_MASK 0x3f |
| 196 | 228 | ||
| 197 | /* Touch status */ | 229 | /* Touch status */ |
| 198 | #define MXT_UNGRIP (1 << 0) | ||
| 199 | #define MXT_SUPPRESS (1 << 1) | 230 | #define MXT_SUPPRESS (1 << 1) |
| 200 | #define MXT_AMP (1 << 2) | 231 | #define MXT_AMP (1 << 2) |
| 201 | #define MXT_VECTOR (1 << 3) | 232 | #define MXT_VECTOR (1 << 3) |
| @@ -212,6 +243,15 @@ | |||
| 212 | /* Touchscreen absolute values */ | 243 | /* Touchscreen absolute values */ |
| 213 | #define MXT_MAX_AREA 0xff | 244 | #define MXT_MAX_AREA 0xff |
| 214 | 245 | ||
| 246 | /* Fixed Report ID values */ | ||
| 247 | #define MXT_RPTID_NOMSG 0xFF /* No messages available to read */ | ||
| 248 | |||
| 249 | #define MXT_MAX_FINGER 10 | ||
| 250 | |||
| 251 | #define RESUME_READS 100 | ||
| 252 | |||
| 253 | #define MXT_DEFAULT_PRESSURE 100 | ||
| 254 | |||
| 215 | struct mxt_info { | 255 | struct mxt_info { |
| 216 | u8 family_id; | 256 | u8 family_id; |
| 217 | u8 variant_id; | 257 | u8 variant_id; |
| @@ -225,37 +265,89 @@ struct mxt_info { | |||
| 225 | struct mxt_object { | 265 | struct mxt_object { |
| 226 | u8 type; | 266 | u8 type; |
| 227 | u16 start_address; | 267 | u16 start_address; |
| 228 | u8 size; /* Size of each instance - 1 */ | 268 | u16 size; |
| 229 | u8 instances; /* Number of instances - 1 */ | 269 | u16 instances; |
| 230 | u8 num_report_ids; | 270 | u8 num_report_ids; |
| 231 | } __packed; | 271 | |
| 272 | /* to map object and message */ | ||
| 273 | u8 min_reportid; | ||
| 274 | u8 max_reportid; | ||
| 275 | }; | ||
| 232 | 276 | ||
| 233 | struct mxt_message { | 277 | struct mxt_message { |
| 234 | u8 reportid; | 278 | u8 reportid; |
| 235 | u8 message[7]; | 279 | u8 message[7]; |
| 280 | u8 checksum; | ||
| 281 | }; | ||
| 282 | |||
| 283 | struct mxt_finger { | ||
| 284 | int status; | ||
| 285 | int x; | ||
| 286 | int y; | ||
| 287 | int area; | ||
| 288 | int pressure; | ||
| 289 | }; | ||
| 290 | |||
| 291 | /* This structure is used to save/restore values during suspend/resume */ | ||
| 292 | struct mxt_suspend { | ||
| 293 | u8 suspend_obj; | ||
| 294 | u8 suspend_reg; | ||
| 295 | u8 suspend_val; | ||
| 296 | u8 suspend_flags; | ||
| 297 | u8 restore_val; | ||
| 236 | }; | 298 | }; |
| 237 | 299 | ||
| 238 | /* Each client has this additional data */ | 300 | /* Each client has this additional data */ |
| 239 | struct mxt_data { | 301 | struct mxt_data { |
| 240 | struct i2c_client *client; | 302 | struct i2c_client *client; |
| 241 | struct input_dev *input_dev; | 303 | struct input_dev *input_dev; |
| 242 | char phys[64]; /* device physical location */ | ||
| 243 | const struct mxt_platform_data *pdata; | 304 | const struct mxt_platform_data *pdata; |
| 244 | struct mxt_object *object_table; | 305 | struct mxt_object *object_table; |
| 245 | struct mxt_info info; | 306 | struct mxt_info info; |
| 307 | struct mxt_finger finger[MXT_MAX_FINGER]; | ||
| 246 | unsigned int irq; | 308 | unsigned int irq; |
| 247 | unsigned int max_x; | 309 | unsigned int max_x; |
| 248 | unsigned int max_y; | 310 | unsigned int max_y; |
| 311 | u8(*read_chg) (void); | ||
| 312 | u16 msg_address; | ||
| 313 | u16 last_address; | ||
| 314 | u8 actv_cycle_time; | ||
| 315 | u8 idle_cycle_time; | ||
| 316 | u8 actv2idle_timeout; | ||
| 317 | u8 is_stopped; | ||
| 318 | struct mutex access_mutex; | ||
| 319 | #if defined(CONFIG_HAS_EARLYSUSPEND) | ||
| 320 | struct early_suspend early_suspend; | ||
| 321 | #endif | ||
| 322 | unsigned int driver_paused; | ||
| 323 | struct bin_attribute mem_access_attr; | ||
| 324 | int debug_enabled; | ||
| 325 | int slowscan_enabled; | ||
| 326 | u8 slowscan_actv_cycle_time; | ||
| 327 | u8 slowscan_idle_cycle_time; | ||
| 328 | u8 slowscan_actv2idle_timeout; | ||
| 329 | u8 slowscan_shad_actv_cycle_time; | ||
| 330 | u8 slowscan_shad_idle_cycle_time; | ||
| 331 | u8 slowscan_shad_actv2idle_timeout; | ||
| 332 | }; | ||
| 249 | 333 | ||
| 250 | /* Cached parameters from object table */ | 334 | static struct mxt_suspend mxt_save[] = { |
| 251 | u8 T6_reportid; | 335 | {MXT_TOUCH_MULTI_T9, MXT_TOUCH_CTRL, MXT_T9_DISABLE, MXT_SUSPEND_DYNAMIC, 0}, |
| 252 | u8 T9_reportid_min; | 336 | {MXT_PROCG_NOISE_T22, MXT_NOISE_CTRL, MXT_T22_DISABLE, MXT_SUSPEND_DYNAMIC, 0}, |
| 253 | u8 T9_reportid_max; | 337 | {MXT_GEN_POWER_T7, MXT_POWER_IDLEACQINT, MXT_T7_IDLEACQ_DISABLE, MXT_SUSPEND_DYNAMIC, 0}, |
| 338 | {MXT_GEN_POWER_T7, MXT_POWER_ACTVACQINT, MXT_T7_ACTVACQ_DISABLE, MXT_SUSPEND_DYNAMIC, 0}, | ||
| 339 | {MXT_GEN_POWER_T7, MXT_POWER_ACTV2IDLETO, MXT_T7_ACTV2IDLE_DISABLE, MXT_SUSPEND_DYNAMIC, 0} | ||
| 254 | }; | 340 | }; |
| 255 | 341 | ||
| 342 | #if defined(CONFIG_HAS_EARLYSUSPEND) | ||
| 343 | static void mxt_early_suspend(struct early_suspend *es); | ||
| 344 | static void mxt_early_resume(struct early_suspend *es); | ||
| 345 | #endif | ||
| 346 | |||
| 256 | static bool mxt_object_readable(unsigned int type) | 347 | static bool mxt_object_readable(unsigned int type) |
| 257 | { | 348 | { |
| 258 | switch (type) { | 349 | switch (type) { |
| 350 | case MXT_GEN_MESSAGE_T5: | ||
| 259 | case MXT_GEN_COMMAND_T6: | 351 | case MXT_GEN_COMMAND_T6: |
| 260 | case MXT_GEN_POWER_T7: | 352 | case MXT_GEN_POWER_T7: |
| 261 | case MXT_GEN_ACQUIRE_T8: | 353 | case MXT_GEN_ACQUIRE_T8: |
| @@ -318,10 +410,17 @@ static bool mxt_object_writable(unsigned int type) | |||
| 318 | } | 410 | } |
| 319 | 411 | ||
| 320 | static void mxt_dump_message(struct device *dev, | 412 | static void mxt_dump_message(struct device *dev, |
| 321 | struct mxt_message *message) | 413 | struct mxt_message *message) |
| 322 | { | 414 | { |
| 323 | dev_dbg(dev, "reportid: %u\tmessage: %*ph\n", | 415 | dev_dbg(dev, "reportid:\t0x%x\n", message->reportid); |
| 324 | message->reportid, 7, message->message); | 416 | dev_dbg(dev, "message1:\t0x%x\n", message->message[0]); |
| 417 | dev_dbg(dev, "message2:\t0x%x\n", message->message[1]); | ||
| 418 | dev_dbg(dev, "message3:\t0x%x\n", message->message[2]); | ||
| 419 | dev_dbg(dev, "message4:\t0x%x\n", message->message[3]); | ||
| 420 | dev_dbg(dev, "message5:\t0x%x\n", message->message[4]); | ||
| 421 | dev_dbg(dev, "message6:\t0x%x\n", message->message[5]); | ||
| 422 | dev_dbg(dev, "message7:\t0x%x\n", message->message[6]); | ||
| 423 | dev_dbg(dev, "checksum:\t0x%x\n", message->checksum); | ||
| 325 | } | 424 | } |
| 326 | 425 | ||
| 327 | static int mxt_check_bootloader(struct i2c_client *client, | 426 | static int mxt_check_bootloader(struct i2c_client *client, |
| @@ -385,36 +484,46 @@ static int mxt_fw_write(struct i2c_client *client, | |||
| 385 | static int __mxt_read_reg(struct i2c_client *client, | 484 | static int __mxt_read_reg(struct i2c_client *client, |
| 386 | u16 reg, u16 len, void *val) | 485 | u16 reg, u16 len, void *val) |
| 387 | { | 486 | { |
| 388 | struct i2c_msg xfer[2]; | ||
| 389 | u8 buf[2]; | 487 | u8 buf[2]; |
| 390 | int ret; | 488 | int retval = 0; |
| 489 | struct mxt_data *data = i2c_get_clientdata(client); | ||
| 391 | 490 | ||
| 392 | buf[0] = reg & 0xff; | 491 | buf[0] = reg & 0xff; |
| 393 | buf[1] = (reg >> 8) & 0xff; | 492 | buf[1] = (reg >> 8) & 0xff; |
| 394 | 493 | ||
| 395 | /* Write register */ | 494 | mutex_lock(&data->access_mutex); |
| 396 | xfer[0].addr = client->addr; | 495 | |
| 397 | xfer[0].flags = 0; | 496 | if ((data->last_address != reg) || (reg != data->msg_address)) { |
| 398 | xfer[0].len = 2; | 497 | if (i2c_master_send(client, (u8 *)buf, 2) != 2) { |
| 399 | xfer[0].buf = buf; | 498 | dev_dbg(&client->dev, "i2c retry\n"); |
| 400 | 499 | msleep(MXT_WAKEUP_TIME); | |
| 401 | /* Read data */ | 500 | |
| 402 | xfer[1].addr = client->addr; | 501 | if (i2c_master_send(client, (u8 *)buf, 2) != 2) { |
| 403 | xfer[1].flags = I2C_M_RD; | 502 | dev_err(&client->dev, "%s: i2c send failed\n", |
| 404 | xfer[1].len = len; | 503 | __func__); |
| 405 | xfer[1].buf = val; | 504 | retval = -EIO; |
| 406 | 505 | goto mxt_read_exit; | |
| 407 | ret = i2c_transfer(client->adapter, xfer, 2); | 506 | } |
| 408 | if (ret == 2) { | 507 | } |
| 409 | ret = 0; | ||
| 410 | } else { | ||
| 411 | if (ret >= 0) | ||
| 412 | ret = -EIO; | ||
| 413 | dev_err(&client->dev, "%s: i2c transfer failed (%d)\n", | ||
| 414 | __func__, ret); | ||
| 415 | } | 508 | } |
| 416 | 509 | ||
| 417 | return ret; | 510 | if (i2c_master_recv(client, (u8 *)val, len) != len) { |
| 511 | dev_dbg(&client->dev, "i2c retry\n"); | ||
| 512 | msleep(MXT_WAKEUP_TIME); | ||
| 513 | |||
| 514 | if (i2c_master_recv(client, (u8 *)val, len) != len) { | ||
| 515 | dev_err(&client->dev, "%s: i2c recv failed\n", | ||
| 516 | __func__); | ||
| 517 | retval = -EIO; | ||
| 518 | goto mxt_read_exit; | ||
| 519 | } | ||
| 520 | } | ||
| 521 | |||
| 522 | data->last_address = reg; | ||
| 523 | |||
| 524 | mxt_read_exit: | ||
| 525 | mutex_unlock(&data->access_mutex); | ||
| 526 | return retval; | ||
| 418 | } | 527 | } |
| 419 | 528 | ||
| 420 | static int mxt_read_reg(struct i2c_client *client, u16 reg, u8 *val) | 529 | static int mxt_read_reg(struct i2c_client *client, u16 reg, u8 *val) |
| @@ -422,39 +531,39 @@ static int mxt_read_reg(struct i2c_client *client, u16 reg, u8 *val) | |||
| 422 | return __mxt_read_reg(client, reg, 1, val); | 531 | return __mxt_read_reg(client, reg, 1, val); |
| 423 | } | 532 | } |
| 424 | 533 | ||
| 425 | static int __mxt_write_reg(struct i2c_client *client, u16 reg, u16 len, | 534 | static int mxt_write_reg(struct i2c_client *client, u16 reg, u8 val) |
| 426 | const void *val) | ||
| 427 | { | 535 | { |
| 428 | u8 *buf; | 536 | u8 buf[3]; |
| 429 | size_t count; | 537 | int retval = 0; |
| 430 | int ret; | 538 | struct mxt_data *data = i2c_get_clientdata(client); |
| 431 | |||
| 432 | count = len + 2; | ||
| 433 | buf = kmalloc(count, GFP_KERNEL); | ||
| 434 | if (!buf) | ||
| 435 | return -ENOMEM; | ||
| 436 | 539 | ||
| 437 | buf[0] = reg & 0xff; | 540 | buf[0] = reg & 0xff; |
| 438 | buf[1] = (reg >> 8) & 0xff; | 541 | buf[1] = (reg >> 8) & 0xff; |
| 439 | memcpy(&buf[2], val, len); | 542 | buf[2] = val; |
| 440 | 543 | ||
| 441 | ret = i2c_master_send(client, buf, count); | 544 | mutex_lock(&data->access_mutex); |
| 442 | if (ret == count) { | 545 | if (i2c_master_send(client, buf, 3) != 3) { |
| 443 | ret = 0; | 546 | dev_dbg(&client->dev, "i2c retry\n"); |
| 444 | } else { | 547 | msleep(MXT_WAKEUP_TIME); |
| 445 | if (ret >= 0) | 548 | |
| 446 | ret = -EIO; | 549 | if (i2c_master_send(client, buf, 3) != 3) { |
| 447 | dev_err(&client->dev, "%s: i2c send failed (%d)\n", | 550 | dev_err(&client->dev, "%s: i2c send failed\n", __func__); |
| 448 | __func__, ret); | 551 | retval = -EIO; |
| 552 | goto mxt_write_exit; | ||
| 553 | } | ||
| 449 | } | 554 | } |
| 555 | data->last_address = reg + 1; | ||
| 450 | 556 | ||
| 451 | kfree(buf); | 557 | mxt_write_exit: |
| 452 | return ret; | 558 | mutex_unlock(&data->access_mutex); |
| 559 | return retval; | ||
| 453 | } | 560 | } |
| 454 | 561 | ||
| 455 | static int mxt_write_reg(struct i2c_client *client, u16 reg, u8 val) | 562 | static int mxt_read_object_table(struct i2c_client *client, |
| 563 | u16 reg, u8 *object_buf) | ||
| 456 | { | 564 | { |
| 457 | return __mxt_write_reg(client, reg, 1, &val); | 565 | return __mxt_read_reg(client, reg, MXT_OBJECT_SIZE, |
| 566 | object_buf); | ||
| 458 | } | 567 | } |
| 459 | 568 | ||
| 460 | static struct mxt_object * | 569 | static struct mxt_object * |
| @@ -469,7 +578,7 @@ mxt_get_object(struct mxt_data *data, u8 type) | |||
| 469 | return object; | 578 | return object; |
| 470 | } | 579 | } |
| 471 | 580 | ||
| 472 | dev_err(&data->client->dev, "Invalid object type\n"); | 581 | dev_err(&data->client->dev, "Invalid object type T%d\n", type); |
| 473 | return NULL; | 582 | return NULL; |
| 474 | } | 583 | } |
| 475 | 584 | ||
| @@ -488,6 +597,20 @@ static int mxt_read_message(struct mxt_data *data, | |||
| 488 | sizeof(struct mxt_message), message); | 597 | sizeof(struct mxt_message), message); |
| 489 | } | 598 | } |
| 490 | 599 | ||
| 600 | static int mxt_read_object(struct mxt_data *data, | ||
| 601 | u8 type, u8 offset, u8 *val) | ||
| 602 | { | ||
| 603 | struct mxt_object *object; | ||
| 604 | u16 reg; | ||
| 605 | |||
| 606 | object = mxt_get_object(data, type); | ||
| 607 | if (!object) | ||
| 608 | return -EINVAL; | ||
| 609 | |||
| 610 | reg = object->start_address; | ||
| 611 | return __mxt_read_reg(data->client, reg + offset, 1, val); | ||
| 612 | } | ||
| 613 | |||
| 491 | static int mxt_write_object(struct mxt_data *data, | 614 | static int mxt_write_object(struct mxt_data *data, |
| 492 | u8 type, u8 offset, u8 val) | 615 | u8 type, u8 offset, u8 val) |
| 493 | { | 616 | { |
| @@ -495,24 +618,80 @@ static int mxt_write_object(struct mxt_data *data, | |||
| 495 | u16 reg; | 618 | u16 reg; |
| 496 | 619 | ||
| 497 | object = mxt_get_object(data, type); | 620 | object = mxt_get_object(data, type); |
| 498 | if (!object || offset >= object->size + 1) | 621 | if (!object) |
| 499 | return -EINVAL; | 622 | return -EINVAL; |
| 500 | 623 | ||
| 501 | reg = object->start_address; | 624 | reg = object->start_address; |
| 502 | return mxt_write_reg(data->client, reg + offset, val); | 625 | return mxt_write_reg(data->client, reg + offset, val); |
| 503 | } | 626 | } |
| 504 | 627 | ||
| 628 | static void mxt_input_report(struct mxt_data *data, int single_id) | ||
| 629 | { | ||
| 630 | struct mxt_finger *finger = data->finger; | ||
| 631 | struct input_dev *input_dev = data->input_dev; | ||
| 632 | int status = finger[single_id].status; | ||
| 633 | int finger_num = 0; | ||
| 634 | int id; | ||
| 635 | |||
| 636 | for (id = 0; id < MXT_MAX_FINGER; id++) { | ||
| 637 | if (!finger[id].status) | ||
| 638 | continue; | ||
| 639 | |||
| 640 | input_report_abs(input_dev, ABS_MT_TOUCH_MAJOR, | ||
| 641 | finger[id].status != MXT_RELEASE ? | ||
| 642 | finger[id].area : 0); | ||
| 643 | input_report_abs(input_dev, ABS_MT_POSITION_X, | ||
| 644 | finger[id].x); | ||
| 645 | input_report_abs(input_dev, ABS_MT_POSITION_Y, | ||
| 646 | finger[id].y); | ||
| 647 | input_report_abs(input_dev, ABS_MT_PRESSURE, | ||
| 648 | finger[id].pressure); | ||
| 649 | input_mt_sync(input_dev); | ||
| 650 | |||
| 651 | if (finger[id].status == MXT_RELEASE) | ||
| 652 | finger[id].status = 0; | ||
| 653 | else | ||
| 654 | finger_num++; | ||
| 655 | } | ||
| 656 | |||
| 657 | input_report_key(input_dev, BTN_TOUCH, finger_num > 0); | ||
| 658 | |||
| 659 | if (status != MXT_RELEASE) { | ||
| 660 | input_report_abs(input_dev, ABS_X, finger[single_id].x); | ||
| 661 | input_report_abs(input_dev, ABS_Y, finger[single_id].y); | ||
| 662 | input_report_abs(input_dev, ABS_PRESSURE, finger[single_id].pressure); | ||
| 663 | } | ||
| 664 | |||
| 665 | input_sync(input_dev); | ||
| 666 | } | ||
| 667 | |||
| 505 | static void mxt_input_touchevent(struct mxt_data *data, | 668 | static void mxt_input_touchevent(struct mxt_data *data, |
| 506 | struct mxt_message *message, int id) | 669 | struct mxt_message *message, int id) |
| 507 | { | 670 | { |
| 671 | struct mxt_finger *finger = data->finger; | ||
| 508 | struct device *dev = &data->client->dev; | 672 | struct device *dev = &data->client->dev; |
| 509 | u8 status = message->message[0]; | 673 | u8 status = message->message[0]; |
| 510 | struct input_dev *input_dev = data->input_dev; | ||
| 511 | int x; | 674 | int x; |
| 512 | int y; | 675 | int y; |
| 513 | int area; | 676 | int area; |
| 514 | int pressure; | 677 | int pressure; |
| 515 | 678 | ||
| 679 | /* Check the touch is present on the screen */ | ||
| 680 | if (!(status & MXT_DETECT)) { | ||
| 681 | if (status & MXT_RELEASE) { | ||
| 682 | dev_dbg(dev, "[%d] released\n", id); | ||
| 683 | |||
| 684 | finger[id].status = MXT_RELEASE; | ||
| 685 | finger[id].pressure = 0; | ||
| 686 | mxt_input_report(data, id); | ||
| 687 | } | ||
| 688 | return; | ||
| 689 | } | ||
| 690 | |||
| 691 | /* Check only AMP detection */ | ||
| 692 | if (!(status & (MXT_PRESS | MXT_MOVE))) | ||
| 693 | return; | ||
| 694 | |||
| 516 | x = (message->message[1] << 4) | ((message->message[3] >> 4) & 0xf); | 695 | x = (message->message[1] << 4) | ((message->message[3] >> 4) & 0xf); |
| 517 | y = (message->message[2] << 4) | ((message->message[3] & 0xf)); | 696 | y = (message->message[2] << 4) | ((message->message[3] & 0xf)); |
| 518 | if (data->max_x < 1024) | 697 | if (data->max_x < 1024) |
| @@ -523,50 +702,31 @@ static void mxt_input_touchevent(struct mxt_data *data, | |||
| 523 | area = message->message[4]; | 702 | area = message->message[4]; |
| 524 | pressure = message->message[5]; | 703 | pressure = message->message[5]; |
| 525 | 704 | ||
| 526 | dev_dbg(dev, | 705 | if ((pressure <= 0) || (pressure > 255)) |
| 527 | "[%u] %c%c%c%c%c%c%c%c x: %5u y: %5u area: %3u amp: %3u\n", | 706 | pressure = MXT_DEFAULT_PRESSURE; |
| 528 | id, | ||
| 529 | (status & MXT_DETECT) ? 'D' : '.', | ||
| 530 | (status & MXT_PRESS) ? 'P' : '.', | ||
| 531 | (status & MXT_RELEASE) ? 'R' : '.', | ||
| 532 | (status & MXT_MOVE) ? 'M' : '.', | ||
| 533 | (status & MXT_VECTOR) ? 'V' : '.', | ||
| 534 | (status & MXT_AMP) ? 'A' : '.', | ||
| 535 | (status & MXT_SUPPRESS) ? 'S' : '.', | ||
| 536 | (status & MXT_UNGRIP) ? 'U' : '.', | ||
| 537 | x, y, area, pressure); | ||
| 538 | |||
| 539 | input_mt_slot(input_dev, id); | ||
| 540 | input_mt_report_slot_state(input_dev, MT_TOOL_FINGER, | ||
| 541 | status & MXT_DETECT); | ||
| 542 | |||
| 543 | if (status & MXT_DETECT) { | ||
| 544 | input_report_abs(input_dev, ABS_MT_POSITION_X, x); | ||
| 545 | input_report_abs(input_dev, ABS_MT_POSITION_Y, y); | ||
| 546 | input_report_abs(input_dev, ABS_MT_PRESSURE, pressure); | ||
| 547 | input_report_abs(input_dev, ABS_MT_TOUCH_MAJOR, area); | ||
| 548 | } | ||
| 549 | } | ||
| 550 | 707 | ||
| 551 | static unsigned mxt_extract_T6_csum(const u8 *csum) | 708 | dev_dbg(dev, "[%d] %s x: %d, y: %d, area: %d\n", id, |
| 552 | { | 709 | status & MXT_MOVE ? "moved" : "pressed", |
| 553 | return csum[0] | (csum[1] << 8) | (csum[2] << 16); | 710 | x, y, area); |
| 554 | } | ||
| 555 | 711 | ||
| 556 | static bool mxt_is_T9_message(struct mxt_data *data, struct mxt_message *msg) | 712 | finger[id].status = status & MXT_MOVE ? |
| 557 | { | 713 | MXT_MOVE : MXT_PRESS; |
| 558 | u8 id = msg->reportid; | 714 | finger[id].x = x; |
| 559 | return (id >= data->T9_reportid_min && id <= data->T9_reportid_max); | 715 | finger[id].y = y; |
| 716 | finger[id].area = area; | ||
| 717 | finger[id].pressure = pressure; | ||
| 718 | |||
| 719 | mxt_input_report(data, id); | ||
| 560 | } | 720 | } |
| 561 | 721 | ||
| 562 | static irqreturn_t mxt_interrupt(int irq, void *dev_id) | 722 | static irqreturn_t mxt_interrupt(int irq, void *dev_id) |
| 563 | { | 723 | { |
| 564 | struct mxt_data *data = dev_id; | 724 | struct mxt_data *data = dev_id; |
| 565 | struct mxt_message message; | 725 | struct mxt_message message; |
| 566 | const u8 *payload = &message.message[0]; | 726 | struct mxt_object *touch_object; |
| 567 | struct device *dev = &data->client->dev; | 727 | struct device *dev = &data->client->dev; |
| 728 | int touchid; | ||
| 568 | u8 reportid; | 729 | u8 reportid; |
| 569 | bool update_input = false; | ||
| 570 | 730 | ||
| 571 | do { | 731 | do { |
| 572 | if (mxt_read_message(data, &message)) { | 732 | if (mxt_read_message(data, &message)) { |
| @@ -576,133 +736,275 @@ static irqreturn_t mxt_interrupt(int irq, void *dev_id) | |||
| 576 | 736 | ||
| 577 | reportid = message.reportid; | 737 | reportid = message.reportid; |
| 578 | 738 | ||
| 579 | if (reportid == data->T6_reportid) { | 739 | touch_object = mxt_get_object(data, MXT_TOUCH_MULTI_T9); |
| 580 | u8 status = payload[0]; | 740 | if (!touch_object) |
| 581 | unsigned csum = mxt_extract_T6_csum(&payload[1]); | 741 | goto end; |
| 582 | dev_dbg(dev, "Status: %02x Config Checksum: %06x\n", | ||
| 583 | status, csum); | ||
| 584 | } else if (mxt_is_T9_message(data, &message)) { | ||
| 585 | int id = reportid - data->T9_reportid_min; | ||
| 586 | mxt_input_touchevent(data, &message, id); | ||
| 587 | update_input = true; | ||
| 588 | } else { | ||
| 589 | mxt_dump_message(dev, &message); | ||
| 590 | } | ||
| 591 | } while (reportid != 0xff); | ||
| 592 | 742 | ||
| 593 | if (update_input) { | 743 | if (data->debug_enabled) |
| 594 | input_mt_report_pointer_emulation(data->input_dev, false); | 744 | print_hex_dump(KERN_DEBUG, "MXT MSG:", DUMP_PREFIX_NONE, |
| 595 | input_sync(data->input_dev); | 745 | 16, 1, &message, sizeof(struct mxt_message), false); |
| 596 | } | 746 | |
| 747 | if (reportid >= touch_object->min_reportid | ||
| 748 | && reportid <= touch_object->max_reportid) { | ||
| 749 | touchid = reportid - touch_object->min_reportid; | ||
| 750 | mxt_input_touchevent(data, &message, touchid); | ||
| 751 | } else if (reportid != MXT_RPTID_NOMSG) | ||
| 752 | mxt_dump_message(dev, &message); | ||
| 753 | } while (reportid != MXT_RPTID_NOMSG); | ||
| 597 | 754 | ||
| 598 | end: | 755 | end: |
| 599 | return IRQ_HANDLED; | 756 | return IRQ_HANDLED; |
| 600 | } | 757 | } |
| 601 | 758 | ||
| 759 | static int mxt_make_highchg(struct mxt_data *data) | ||
| 760 | { | ||
| 761 | struct device *dev = &data->client->dev; | ||
| 762 | struct mxt_message message; | ||
| 763 | int count = 30; | ||
| 764 | int error; | ||
| 765 | |||
| 766 | /* Read dummy message to make high CHG pin */ | ||
| 767 | do { | ||
| 768 | error = mxt_read_message(data, &message); | ||
| 769 | if (error) | ||
| 770 | return error; | ||
| 771 | } while (message.reportid != MXT_RPTID_NOMSG && --count); | ||
| 772 | |||
| 773 | if (!count) { | ||
| 774 | dev_err(dev, "CHG pin isn't cleared\n"); | ||
| 775 | return -EBUSY; | ||
| 776 | } | ||
| 777 | |||
| 778 | return 0; | ||
| 779 | } | ||
| 780 | |||
| 602 | static int mxt_check_reg_init(struct mxt_data *data) | 781 | static int mxt_check_reg_init(struct mxt_data *data) |
| 603 | { | 782 | { |
| 783 | struct i2c_client *client = data->client; | ||
| 604 | const struct mxt_platform_data *pdata = data->pdata; | 784 | const struct mxt_platform_data *pdata = data->pdata; |
| 605 | struct mxt_object *object; | 785 | struct mxt_object *object; |
| 786 | struct mxt_message message; | ||
| 606 | struct device *dev = &data->client->dev; | 787 | struct device *dev = &data->client->dev; |
| 607 | int index = 0; | 788 | int index = 0; |
| 608 | int i, size; | 789 | int timeout_counter = 0; |
| 609 | int ret; | 790 | int i, j, config_offset; |
| 791 | int error; | ||
| 792 | unsigned long current_crc; | ||
| 793 | u8 command_register; | ||
| 610 | 794 | ||
| 611 | if (!pdata->config) { | 795 | if (!pdata->config) { |
| 612 | dev_dbg(dev, "No cfg data defined, skipping reg init\n"); | 796 | dev_dbg(dev, "No cfg data defined, skipping reg init\n"); |
| 613 | return 0; | 797 | return 0; |
| 614 | } | 798 | } |
| 615 | 799 | ||
| 800 | /* Try to read the config checksum of the existing cfg */ | ||
| 801 | mxt_write_object(data, MXT_GEN_COMMAND_T6, | ||
| 802 | MXT_COMMAND_REPORTALL, 1); | ||
| 803 | msleep(30); | ||
| 804 | |||
| 805 | error = mxt_read_message(data, &message); | ||
| 806 | if (error) | ||
| 807 | return error; | ||
| 808 | |||
| 809 | object = mxt_get_object(data, MXT_GEN_COMMAND_T6); | ||
| 810 | if (!object) | ||
| 811 | return -EIO; | ||
| 812 | |||
| 813 | /* Check if this message is from command processor (which has | ||
| 814 | only one reporting ID), if so, bytes 1-3 are the checksum. */ | ||
| 815 | if (message.reportid == object->max_reportid) { | ||
| 816 | current_crc = message.message[1] | (message.message[2] << 8) | | ||
| 817 | (message.message[3] << 16); | ||
| 818 | } else { | ||
| 819 | dev_info(dev, "Couldn't retrieve the current cfg checksum, " | ||
| 820 | "forcing load\n"); | ||
| 821 | current_crc = 0xFFFFFFFF; | ||
| 822 | } | ||
| 823 | dev_info(dev, | ||
| 824 | "Config CRC read from the mXT: %X\n", | ||
| 825 | (unsigned int) current_crc); | ||
| 826 | |||
| 827 | if (current_crc == pdata->config_crc) { | ||
| 828 | dev_info(dev, | ||
| 829 | "Matching CRC's, skipping CFG load.\n"); | ||
| 830 | return 0; | ||
| 831 | } else { | ||
| 832 | dev_info(dev, "Doesn't match platform data config CRC (%X), " | ||
| 833 | "writing config from platform data...\n", | ||
| 834 | (unsigned int) pdata->config_crc); | ||
| 835 | } | ||
| 836 | |||
| 616 | for (i = 0; i < data->info.object_num; i++) { | 837 | for (i = 0; i < data->info.object_num; i++) { |
| 617 | object = data->object_table + i; | 838 | object = data->object_table + i; |
| 618 | 839 | ||
| 619 | if (!mxt_object_writable(object->type)) | 840 | if (!mxt_object_writable(object->type)) |
| 620 | continue; | 841 | continue; |
| 621 | 842 | dev_info(dev, "Writing object type %d, config offset %d", data->object_table[i].type, index); | |
| 622 | size = (object->size + 1) * (object->instances + 1); | 843 | for (j = 0; |
| 623 | if (index + size > pdata->config_length) { | 844 | j < object->size * object->instances; |
| 624 | dev_err(dev, "Not enough config data!\n"); | 845 | j++) { |
| 625 | return -EINVAL; | 846 | config_offset = index + j; |
| 847 | if (config_offset > pdata->config_length) { | ||
| 848 | dev_err(dev, "Not enough config data!\n"); | ||
| 849 | dev_err(dev, "config base is %d, offset is %d\n", index, config_offset); | ||
| 850 | return -EINVAL; | ||
| 851 | } | ||
| 852 | mxt_write_object(data, object->type, j, | ||
| 853 | pdata->config[config_offset]); | ||
| 626 | } | 854 | } |
| 855 | index += object->size * object->instances; | ||
| 856 | } | ||
| 857 | dev_info(dev, "Config written!"); | ||
| 627 | 858 | ||
| 628 | ret = __mxt_write_reg(data->client, object->start_address, | 859 | error = mxt_make_highchg(data); |
| 629 | size, &pdata->config[index]); | 860 | if (error) |
| 630 | if (ret) | 861 | return error; |
| 631 | return ret; | 862 | |
| 632 | index += size; | 863 | /* Backup to memory */ |
| 864 | mxt_write_object(data, MXT_GEN_COMMAND_T6, | ||
| 865 | MXT_COMMAND_BACKUPNV, | ||
| 866 | MXT_BACKUP_VALUE); | ||
| 867 | msleep(MXT_BACKUP_TIME); | ||
| 868 | do { | ||
| 869 | error = mxt_read_object(data, MXT_GEN_COMMAND_T6, | ||
| 870 | MXT_COMMAND_BACKUPNV, | ||
| 871 | &command_register); | ||
| 872 | if (error) | ||
| 873 | return error; | ||
| 874 | msleep(10); | ||
| 875 | } while ((command_register != 0) && (timeout_counter++ <= 100)); | ||
| 876 | if (timeout_counter > 100) { | ||
| 877 | dev_err(&client->dev, "No response after backup!\n"); | ||
| 878 | return -EIO; | ||
| 879 | } | ||
| 880 | |||
| 881 | /* Clear the interrupt line */ | ||
| 882 | error = mxt_make_highchg(data); | ||
| 883 | if (error) | ||
| 884 | return error; | ||
| 885 | |||
| 886 | /* Soft reset */ | ||
| 887 | mxt_write_object(data, MXT_GEN_COMMAND_T6, | ||
| 888 | MXT_COMMAND_RESET, 1); | ||
| 889 | if (data->pdata->read_chg == NULL) { | ||
| 890 | msleep(MXT_RESET_NOCHGREAD); | ||
| 891 | } else { | ||
| 892 | switch (data->info.family_id) { | ||
| 893 | case MXT224_ID: | ||
| 894 | msleep(MXT224_RESET_TIME); | ||
| 895 | break; | ||
| 896 | case MXT768E_ID: | ||
| 897 | msleep(MXT768E_RESET_TIME); | ||
| 898 | break; | ||
| 899 | case MXT1386_ID: | ||
| 900 | msleep(MXT1386_RESET_TIME); | ||
| 901 | break; | ||
| 902 | default: | ||
| 903 | msleep(MXT_RESET_TIME); | ||
| 904 | } | ||
| 905 | timeout_counter = 0; | ||
| 906 | while ((timeout_counter++ <= 100) && data->pdata->read_chg()) | ||
| 907 | msleep(10); | ||
| 908 | if (timeout_counter > 100) { | ||
| 909 | dev_err(&client->dev, "No response after reset!\n"); | ||
| 910 | return -EIO; | ||
| 911 | } | ||
| 633 | } | 912 | } |
| 634 | 913 | ||
| 635 | return 0; | 914 | return 0; |
| 636 | } | 915 | } |
| 637 | 916 | ||
| 638 | static int mxt_make_highchg(struct mxt_data *data) | 917 | |
| 918 | static void mxt_handle_pdata(struct mxt_data *data) | ||
| 919 | { | ||
| 920 | const struct mxt_platform_data *pdata = data->pdata; | ||
| 921 | |||
| 922 | if (pdata->read_chg != NULL) | ||
| 923 | data->read_chg = pdata->read_chg; | ||
| 924 | } | ||
| 925 | |||
| 926 | static int mxt_set_power_cfg(struct mxt_data *data, u8 sleep) | ||
| 639 | { | 927 | { |
| 640 | struct device *dev = &data->client->dev; | 928 | struct device *dev = &data->client->dev; |
| 641 | struct mxt_message message; | ||
| 642 | int count = 10; | ||
| 643 | int error; | 929 | int error; |
| 930 | u8 actv_cycle_time = 0; | ||
| 931 | u8 idle_cycle_time = 0; | ||
| 932 | u8 actv2idle_timeout = data->actv2idle_timeout; | ||
| 644 | 933 | ||
| 645 | /* Read dummy message to make high CHG pin */ | 934 | if (!sleep) { |
| 646 | do { | 935 | actv_cycle_time = data->actv_cycle_time; |
| 647 | error = mxt_read_message(data, &message); | 936 | idle_cycle_time = data->idle_cycle_time; |
| 648 | if (error) | ||
| 649 | return error; | ||
| 650 | } while (message.reportid != 0xff && --count); | ||
| 651 | |||
| 652 | if (!count) { | ||
| 653 | dev_err(dev, "CHG pin isn't cleared\n"); | ||
| 654 | return -EBUSY; | ||
| 655 | } | 937 | } |
| 656 | 938 | ||
| 939 | error = mxt_write_object(data, MXT_GEN_POWER_T7, MXT_POWER_ACTVACQINT, | ||
| 940 | actv_cycle_time); | ||
| 941 | if (error) | ||
| 942 | goto i2c_error; | ||
| 943 | |||
| 944 | error = mxt_write_object(data, MXT_GEN_POWER_T7, MXT_POWER_IDLEACQINT, | ||
| 945 | idle_cycle_time); | ||
| 946 | if (error) | ||
| 947 | goto i2c_error; | ||
| 948 | |||
| 949 | error = mxt_write_object(data, MXT_GEN_POWER_T7, MXT_POWER_ACTV2IDLETO, | ||
| 950 | actv2idle_timeout); | ||
| 951 | if (error) | ||
| 952 | goto i2c_error; | ||
| 953 | |||
| 954 | dev_dbg(dev, "%s: Set ACTV %d, IDLE %d", __func__, | ||
| 955 | actv_cycle_time, idle_cycle_time); | ||
| 956 | |||
| 657 | return 0; | 957 | return 0; |
| 958 | |||
| 959 | i2c_error: | ||
| 960 | dev_err(dev, "Failed to set power cfg"); | ||
| 961 | return error; | ||
| 658 | } | 962 | } |
| 659 | 963 | ||
| 660 | static void mxt_handle_pdata(struct mxt_data *data) | 964 | static int mxt_init_power_cfg(struct mxt_data *data) |
| 661 | { | 965 | { |
| 662 | const struct mxt_platform_data *pdata = data->pdata; | 966 | const struct mxt_platform_data *pdata = data->pdata; |
| 663 | u8 voltage; | 967 | struct device *dev = &data->client->dev; |
| 664 | 968 | int error; | |
| 665 | /* Set touchscreen lines */ | 969 | |
| 666 | mxt_write_object(data, MXT_TOUCH_MULTI_T9, MXT_TOUCH_XSIZE, | 970 | data->slowscan_actv_cycle_time = 120; /* 120mS */ |
| 667 | pdata->x_line); | 971 | data->slowscan_idle_cycle_time = 10; /* 10mS */ |
| 668 | mxt_write_object(data, MXT_TOUCH_MULTI_T9, MXT_TOUCH_YSIZE, | 972 | data->slowscan_actv2idle_timeout = 100; /* 10 seconds */ |
| 669 | pdata->y_line); | 973 | if (pdata->actv_cycle_time > 0 && pdata->idle_cycle_time > 0) { |
| 670 | 974 | data->actv_cycle_time = pdata->actv_cycle_time; | |
| 671 | /* Set touchscreen orient */ | 975 | data->idle_cycle_time = pdata->idle_cycle_time; |
| 672 | mxt_write_object(data, MXT_TOUCH_MULTI_T9, MXT_TOUCH_ORIENT, | 976 | } else { |
| 673 | pdata->orient); | 977 | error = mxt_read_object(data, MXT_GEN_POWER_T7, |
| 674 | 978 | MXT_POWER_ACTVACQINT, | |
| 675 | /* Set touchscreen burst length */ | 979 | &data->actv_cycle_time); |
| 676 | mxt_write_object(data, MXT_TOUCH_MULTI_T9, | 980 | |
| 677 | MXT_TOUCH_BLEN, pdata->blen); | 981 | if (error) |
| 678 | 982 | return error; | |
| 679 | /* Set touchscreen threshold */ | 983 | |
| 680 | mxt_write_object(data, MXT_TOUCH_MULTI_T9, | 984 | error = mxt_read_object(data, MXT_GEN_POWER_T7, |
| 681 | MXT_TOUCH_TCHTHR, pdata->threshold); | 985 | MXT_POWER_IDLEACQINT, |
| 682 | 986 | &data->idle_cycle_time); | |
| 683 | /* Set touchscreen resolution */ | 987 | |
| 684 | mxt_write_object(data, MXT_TOUCH_MULTI_T9, | 988 | if (error) |
| 685 | MXT_TOUCH_XRANGE_LSB, (pdata->x_size - 1) & 0xff); | 989 | return error; |
| 686 | mxt_write_object(data, MXT_TOUCH_MULTI_T9, | ||
| 687 | MXT_TOUCH_XRANGE_MSB, (pdata->x_size - 1) >> 8); | ||
| 688 | mxt_write_object(data, MXT_TOUCH_MULTI_T9, | ||
| 689 | MXT_TOUCH_YRANGE_LSB, (pdata->y_size - 1) & 0xff); | ||
| 690 | mxt_write_object(data, MXT_TOUCH_MULTI_T9, | ||
| 691 | MXT_TOUCH_YRANGE_MSB, (pdata->y_size - 1) >> 8); | ||
| 692 | |||
| 693 | /* Set touchscreen voltage */ | ||
| 694 | if (pdata->voltage) { | ||
| 695 | if (pdata->voltage < MXT_VOLTAGE_DEFAULT) { | ||
| 696 | voltage = (MXT_VOLTAGE_DEFAULT - pdata->voltage) / | ||
| 697 | MXT_VOLTAGE_STEP; | ||
| 698 | voltage = 0xff - voltage + 1; | ||
| 699 | } else | ||
| 700 | voltage = (pdata->voltage - MXT_VOLTAGE_DEFAULT) / | ||
| 701 | MXT_VOLTAGE_STEP; | ||
| 702 | |||
| 703 | mxt_write_object(data, MXT_SPT_CTECONFIG_T28, | ||
| 704 | MXT_CTE_VOLTAGE, voltage); | ||
| 705 | } | 990 | } |
| 991 | |||
| 992 | error = mxt_read_object(data, MXT_GEN_POWER_T7, | ||
| 993 | MXT_POWER_ACTV2IDLETO, | ||
| 994 | &data->actv2idle_timeout); | ||
| 995 | |||
| 996 | if (error) | ||
| 997 | return error; | ||
| 998 | |||
| 999 | /* On init, power up */ | ||
| 1000 | error = mxt_set_power_cfg(data, 0); | ||
| 1001 | if (error) | ||
| 1002 | return error; | ||
| 1003 | |||
| 1004 | dev_info(dev, "Initialised power cfg: ACTV %d, IDLE %d", | ||
| 1005 | data->actv_cycle_time, data->idle_cycle_time); | ||
| 1006 | |||
| 1007 | return 0; | ||
| 706 | } | 1008 | } |
| 707 | 1009 | ||
| 708 | static int mxt_get_info(struct mxt_data *data) | 1010 | static int mxt_get_info(struct mxt_data *data) |
| @@ -710,82 +1012,89 @@ static int mxt_get_info(struct mxt_data *data) | |||
| 710 | struct i2c_client *client = data->client; | 1012 | struct i2c_client *client = data->client; |
| 711 | struct mxt_info *info = &data->info; | 1013 | struct mxt_info *info = &data->info; |
| 712 | int error; | 1014 | int error; |
| 1015 | u8 val; | ||
| 1016 | |||
| 1017 | /* force send of address pointer on first read during probe */ | ||
| 1018 | data->last_address = -1; | ||
| 1019 | |||
| 1020 | error = mxt_read_reg(client, MXT_FAMILY_ID, &val); | ||
| 1021 | if (error) | ||
| 1022 | return error; | ||
| 1023 | info->family_id = val; | ||
| 1024 | |||
| 1025 | error = mxt_read_reg(client, MXT_VARIANT_ID, &val); | ||
| 1026 | if (error) | ||
| 1027 | return error; | ||
| 1028 | info->variant_id = val; | ||
| 1029 | |||
| 1030 | error = mxt_read_reg(client, MXT_VERSION, &val); | ||
| 1031 | if (error) | ||
| 1032 | return error; | ||
| 1033 | info->version = val; | ||
| 713 | 1034 | ||
| 714 | /* Read 7-byte info block starting at address 0 */ | 1035 | error = mxt_read_reg(client, MXT_BUILD, &val); |
| 715 | error = __mxt_read_reg(client, MXT_INFO, sizeof(*info), info); | ||
| 716 | if (error) | 1036 | if (error) |
| 717 | return error; | 1037 | return error; |
| 1038 | info->build = val; | ||
| 1039 | |||
| 1040 | error = mxt_read_reg(client, MXT_OBJECT_NUM, &val); | ||
| 1041 | if (error) | ||
| 1042 | return error; | ||
| 1043 | info->object_num = val; | ||
| 718 | 1044 | ||
| 719 | return 0; | 1045 | return 0; |
| 720 | } | 1046 | } |
| 721 | 1047 | ||
| 722 | static int mxt_get_object_table(struct mxt_data *data) | 1048 | static int mxt_get_object_table(struct mxt_data *data) |
| 723 | { | 1049 | { |
| 724 | struct i2c_client *client = data->client; | 1050 | struct device *dev = &data->client->dev; |
| 725 | size_t table_size; | ||
| 726 | int error; | 1051 | int error; |
| 727 | int i; | 1052 | int i; |
| 728 | u8 reportid; | 1053 | u16 reg; |
| 729 | 1054 | u8 reportid = 0; | |
| 730 | table_size = data->info.object_num * sizeof(struct mxt_object); | 1055 | u8 buf[MXT_OBJECT_SIZE]; |
| 731 | error = __mxt_read_reg(client, MXT_OBJECT_START, table_size, | ||
| 732 | data->object_table); | ||
| 733 | if (error) | ||
| 734 | return error; | ||
| 735 | 1056 | ||
| 736 | /* Valid Report IDs start counting from 1 */ | ||
| 737 | reportid = 1; | ||
| 738 | for (i = 0; i < data->info.object_num; i++) { | 1057 | for (i = 0; i < data->info.object_num; i++) { |
| 739 | struct mxt_object *object = data->object_table + i; | 1058 | struct mxt_object *object = data->object_table + i; |
| 740 | u8 min_id, max_id; | ||
| 741 | 1059 | ||
| 742 | le16_to_cpus(&object->start_address); | 1060 | reg = MXT_OBJECT_START + MXT_OBJECT_SIZE * i; |
| 1061 | error = mxt_read_object_table(data->client, reg, buf); | ||
| 1062 | if (error) | ||
| 1063 | return error; | ||
| 1064 | |||
| 1065 | object->type = buf[0]; | ||
| 1066 | object->start_address = (buf[2] << 8) | buf[1]; | ||
| 1067 | object->size = buf[3] + 1; | ||
| 1068 | object->instances = buf[4] + 1; | ||
| 1069 | object->num_report_ids = buf[5]; | ||
| 743 | 1070 | ||
| 744 | if (object->num_report_ids) { | 1071 | if (object->num_report_ids) { |
| 745 | min_id = reportid; | 1072 | reportid += object->num_report_ids * object->instances; |
| 746 | reportid += object->num_report_ids * | 1073 | object->max_reportid = reportid; |
| 747 | (object->instances + 1); | 1074 | object->min_reportid = object->max_reportid - |
| 748 | max_id = reportid - 1; | 1075 | object->instances * object->num_report_ids + 1; |
| 749 | } else { | ||
| 750 | min_id = 0; | ||
| 751 | max_id = 0; | ||
| 752 | } | 1076 | } |
| 753 | 1077 | ||
| 754 | dev_dbg(&data->client->dev, | 1078 | /* Store message window address so we don't have to |
| 755 | "Type %2d Start %3d Size %3d Instances %2d ReportIDs %3u : %3u\n", | 1079 | search the object table every time we read message */ |
| 756 | object->type, object->start_address, object->size + 1, | 1080 | if (object->type == MXT_GEN_MESSAGE_T5) |
| 757 | object->instances + 1, min_id, max_id); | 1081 | data->msg_address = object->start_address; |
| 758 | 1082 | ||
| 759 | switch (object->type) { | 1083 | dev_dbg(dev, "T%d, start:%d size:%d instances:%d " |
| 760 | case MXT_GEN_COMMAND_T6: | 1084 | "min_reportid:%d max_reportid:%d\n", |
| 761 | data->T6_reportid = min_id; | 1085 | object->type, object->start_address, object->size, |
| 762 | break; | 1086 | object->instances, |
| 763 | case MXT_TOUCH_MULTI_T9: | 1087 | object->min_reportid, object->max_reportid); |
| 764 | data->T9_reportid_min = min_id; | ||
| 765 | data->T9_reportid_max = max_id; | ||
| 766 | break; | ||
| 767 | } | ||
| 768 | } | 1088 | } |
| 769 | 1089 | ||
| 770 | return 0; | 1090 | return 0; |
| 771 | } | 1091 | } |
| 772 | 1092 | ||
| 773 | static void mxt_free_object_table(struct mxt_data *data) | ||
| 774 | { | ||
| 775 | kfree(data->object_table); | ||
| 776 | data->object_table = NULL; | ||
| 777 | data->T6_reportid = 0; | ||
| 778 | data->T9_reportid_min = 0; | ||
| 779 | data->T9_reportid_max = 0; | ||
| 780 | |||
| 781 | } | ||
| 782 | |||
| 783 | static int mxt_initialize(struct mxt_data *data) | 1093 | static int mxt_initialize(struct mxt_data *data) |
| 784 | { | 1094 | { |
| 785 | struct i2c_client *client = data->client; | 1095 | struct i2c_client *client = data->client; |
| 786 | struct mxt_info *info = &data->info; | 1096 | struct mxt_info *info = &data->info; |
| 787 | int error; | 1097 | int error; |
| 788 | u8 val; | ||
| 789 | 1098 | ||
| 790 | error = mxt_get_info(data); | 1099 | error = mxt_get_info(data); |
| 791 | if (error) | 1100 | if (error) |
| @@ -801,53 +1110,37 @@ static int mxt_initialize(struct mxt_data *data) | |||
| 801 | 1110 | ||
| 802 | /* Get object table information */ | 1111 | /* Get object table information */ |
| 803 | error = mxt_get_object_table(data); | 1112 | error = mxt_get_object_table(data); |
| 804 | if (error) | 1113 | if (error) { |
| 805 | goto err_free_object_table; | 1114 | dev_err(&client->dev, "Failed to read object table\n"); |
| 1115 | return error; | ||
| 1116 | } | ||
| 806 | 1117 | ||
| 807 | /* Check register init values */ | 1118 | /* Load initial touch chip configuration */ |
| 808 | error = mxt_check_reg_init(data); | 1119 | error = mxt_check_reg_init(data); |
| 809 | if (error) | 1120 | if (error) { |
| 810 | goto err_free_object_table; | 1121 | dev_err(&client->dev, "Failed to initialize configuration\n"); |
| 1122 | return error; | ||
| 1123 | } | ||
| 811 | 1124 | ||
| 812 | mxt_handle_pdata(data); | 1125 | mxt_handle_pdata(data); |
| 813 | 1126 | ||
| 814 | /* Backup to memory */ | 1127 | error = mxt_init_power_cfg(data); |
| 815 | mxt_write_object(data, MXT_GEN_COMMAND_T6, | 1128 | if (error) { |
| 816 | MXT_COMMAND_BACKUPNV, | 1129 | dev_err(&client->dev, "Failed to initialize power cfg\n"); |
| 817 | MXT_BACKUP_VALUE); | 1130 | return error; |
| 818 | msleep(MXT_BACKUP_TIME); | 1131 | } |
| 819 | |||
| 820 | /* Soft reset */ | ||
| 821 | mxt_write_object(data, MXT_GEN_COMMAND_T6, | ||
| 822 | MXT_COMMAND_RESET, 1); | ||
| 823 | msleep(MXT_RESET_TIME); | ||
| 824 | |||
| 825 | /* Update matrix size at info struct */ | ||
| 826 | error = mxt_read_reg(client, MXT_MATRIX_X_SIZE, &val); | ||
| 827 | if (error) | ||
| 828 | goto err_free_object_table; | ||
| 829 | info->matrix_xsize = val; | ||
| 830 | |||
| 831 | error = mxt_read_reg(client, MXT_MATRIX_Y_SIZE, &val); | ||
| 832 | if (error) | ||
| 833 | goto err_free_object_table; | ||
| 834 | info->matrix_ysize = val; | ||
| 835 | 1132 | ||
| 836 | dev_info(&client->dev, | 1133 | dev_info(&client->dev, |
| 837 | "Family ID: %u Variant ID: %u Major.Minor.Build: %u.%u.%02X\n", | 1134 | "Family ID: %d Variant ID: %d Version: %d Build: %d\n", |
| 838 | info->family_id, info->variant_id, info->version >> 4, | 1135 | info->family_id, info->variant_id, info->version, |
| 839 | info->version & 0xf, info->build); | 1136 | info->build); |
| 840 | 1137 | ||
| 841 | dev_info(&client->dev, | 1138 | dev_info(&client->dev, |
| 842 | "Matrix X Size: %u Matrix Y Size: %u Object Num: %u\n", | 1139 | "Matrix X Size: %d Matrix Y Size: %d Object Num: %d\n", |
| 843 | info->matrix_xsize, info->matrix_ysize, | 1140 | info->matrix_xsize, info->matrix_ysize, |
| 844 | info->object_num); | 1141 | info->object_num); |
| 845 | 1142 | ||
| 846 | return 0; | 1143 | return 0; |
| 847 | |||
| 848 | err_free_object_table: | ||
| 849 | mxt_free_object_table(data); | ||
| 850 | return error; | ||
| 851 | } | 1144 | } |
| 852 | 1145 | ||
| 853 | static void mxt_calc_resolution(struct mxt_data *data) | 1146 | static void mxt_calc_resolution(struct mxt_data *data) |
| @@ -864,44 +1157,6 @@ static void mxt_calc_resolution(struct mxt_data *data) | |||
| 864 | } | 1157 | } |
| 865 | } | 1158 | } |
| 866 | 1159 | ||
| 867 | /* Firmware Version is returned as Major.Minor.Build */ | ||
| 868 | static ssize_t mxt_fw_version_show(struct device *dev, | ||
| 869 | struct device_attribute *attr, char *buf) | ||
| 870 | { | ||
| 871 | struct mxt_data *data = dev_get_drvdata(dev); | ||
| 872 | struct mxt_info *info = &data->info; | ||
| 873 | return scnprintf(buf, PAGE_SIZE, "%u.%u.%02X\n", | ||
| 874 | info->version >> 4, info->version & 0xf, info->build); | ||
| 875 | } | ||
| 876 | |||
| 877 | /* Hardware Version is returned as FamilyID.VariantID */ | ||
| 878 | static ssize_t mxt_hw_version_show(struct device *dev, | ||
| 879 | struct device_attribute *attr, char *buf) | ||
| 880 | { | ||
| 881 | struct mxt_data *data = dev_get_drvdata(dev); | ||
| 882 | struct mxt_info *info = &data->info; | ||
| 883 | return scnprintf(buf, PAGE_SIZE, "%u.%u\n", | ||
| 884 | info->family_id, info->variant_id); | ||
| 885 | } | ||
| 886 | |||
| 887 | static ssize_t mxt_show_instance(char *buf, int count, | ||
| 888 | struct mxt_object *object, int instance, | ||
| 889 | const u8 *val) | ||
| 890 | { | ||
| 891 | int i; | ||
| 892 | |||
| 893 | if (object->instances > 0) | ||
| 894 | count += scnprintf(buf + count, PAGE_SIZE - count, | ||
| 895 | "Instance %u\n", instance); | ||
| 896 | |||
| 897 | for (i = 0; i < object->size + 1; i++) | ||
| 898 | count += scnprintf(buf + count, PAGE_SIZE - count, | ||
| 899 | "\t[%2u]: %02x (%d)\n", i, val[i], val[i]); | ||
| 900 | count += scnprintf(buf + count, PAGE_SIZE - count, "\n"); | ||
| 901 | |||
| 902 | return count; | ||
| 903 | } | ||
| 904 | |||
| 905 | static ssize_t mxt_object_show(struct device *dev, | 1160 | static ssize_t mxt_object_show(struct device *dev, |
| 906 | struct device_attribute *attr, char *buf) | 1161 | struct device_attribute *attr, char *buf) |
| 907 | { | 1162 | { |
| @@ -910,38 +1165,43 @@ static ssize_t mxt_object_show(struct device *dev, | |||
| 910 | int count = 0; | 1165 | int count = 0; |
| 911 | int i, j; | 1166 | int i, j; |
| 912 | int error; | 1167 | int error; |
| 913 | u8 *obuf; | 1168 | u8 val; |
| 914 | |||
| 915 | /* Pre-allocate buffer large enough to hold max sized object. */ | ||
| 916 | obuf = kmalloc(256, GFP_KERNEL); | ||
| 917 | if (!obuf) | ||
| 918 | return -ENOMEM; | ||
| 919 | 1169 | ||
| 920 | error = 0; | ||
| 921 | for (i = 0; i < data->info.object_num; i++) { | 1170 | for (i = 0; i < data->info.object_num; i++) { |
| 922 | object = data->object_table + i; | 1171 | object = data->object_table + i; |
| 923 | 1172 | ||
| 924 | if (!mxt_object_readable(object->type)) | 1173 | count += snprintf(buf + count, PAGE_SIZE - count, |
| 1174 | "Object[%d] (Type %d)\n", | ||
| 1175 | i + 1, object->type); | ||
| 1176 | if (count >= PAGE_SIZE) | ||
| 1177 | return PAGE_SIZE - 1; | ||
| 1178 | |||
| 1179 | if (!mxt_object_readable(object->type)) { | ||
| 1180 | count += snprintf(buf + count, PAGE_SIZE - count, | ||
| 1181 | "\n"); | ||
| 1182 | if (count >= PAGE_SIZE) | ||
| 1183 | return PAGE_SIZE - 1; | ||
| 925 | continue; | 1184 | continue; |
| 1185 | } | ||
| 926 | 1186 | ||
| 927 | count += scnprintf(buf + count, PAGE_SIZE - count, | 1187 | for (j = 0; j < object->size; j++) { |
| 928 | "T%u:\n", object->type); | 1188 | error = mxt_read_object(data, |
| 929 | 1189 | object->type, j, &val); | |
| 930 | for (j = 0; j < object->instances + 1; j++) { | ||
| 931 | u16 size = object->size + 1; | ||
| 932 | u16 addr = object->start_address + j * size; | ||
| 933 | |||
| 934 | error = __mxt_read_reg(data->client, addr, size, obuf); | ||
| 935 | if (error) | 1190 | if (error) |
| 936 | goto done; | 1191 | return error; |
| 937 | 1192 | ||
| 938 | count = mxt_show_instance(buf, count, object, j, obuf); | 1193 | count += snprintf(buf + count, PAGE_SIZE - count, |
| 1194 | "\t[%2d]: %02x (%d)\n", j, val, val); | ||
| 1195 | if (count >= PAGE_SIZE) | ||
| 1196 | return PAGE_SIZE - 1; | ||
| 939 | } | 1197 | } |
| 1198 | |||
| 1199 | count += snprintf(buf + count, PAGE_SIZE - count, "\n"); | ||
| 1200 | if (count >= PAGE_SIZE) | ||
| 1201 | return PAGE_SIZE - 1; | ||
| 940 | } | 1202 | } |
| 941 | 1203 | ||
| 942 | done: | 1204 | return count; |
| 943 | kfree(obuf); | ||
| 944 | return error ?: count; | ||
| 945 | } | 1205 | } |
| 946 | 1206 | ||
| 947 | static int mxt_load_fw(struct device *dev, const char *fn) | 1207 | static int mxt_load_fw(struct device *dev, const char *fn) |
| @@ -1034,7 +1294,8 @@ static ssize_t mxt_update_fw_store(struct device *dev, | |||
| 1034 | /* Wait for reset */ | 1294 | /* Wait for reset */ |
| 1035 | msleep(MXT_FWRESET_TIME); | 1295 | msleep(MXT_FWRESET_TIME); |
| 1036 | 1296 | ||
| 1037 | mxt_free_object_table(data); | 1297 | kfree(data->object_table); |
| 1298 | data->object_table = NULL; | ||
| 1038 | 1299 | ||
| 1039 | mxt_initialize(data); | 1300 | mxt_initialize(data); |
| 1040 | } | 1301 | } |
| @@ -1048,16 +1309,240 @@ static ssize_t mxt_update_fw_store(struct device *dev, | |||
| 1048 | return count; | 1309 | return count; |
| 1049 | } | 1310 | } |
| 1050 | 1311 | ||
| 1051 | static DEVICE_ATTR(fw_version, S_IRUGO, mxt_fw_version_show, NULL); | 1312 | static ssize_t mxt_pause_show(struct device *dev, |
| 1052 | static DEVICE_ATTR(hw_version, S_IRUGO, mxt_hw_version_show, NULL); | 1313 | struct device_attribute *attr, char *buf) |
| 1053 | static DEVICE_ATTR(object, S_IRUGO, mxt_object_show, NULL); | 1314 | { |
| 1054 | static DEVICE_ATTR(update_fw, S_IWUSR, NULL, mxt_update_fw_store); | 1315 | struct mxt_data *data = dev_get_drvdata(dev); |
| 1316 | int count = 0; | ||
| 1317 | |||
| 1318 | count += sprintf(buf + count, "%d", data->driver_paused); | ||
| 1319 | count += sprintf(buf + count, "\n"); | ||
| 1320 | |||
| 1321 | return count; | ||
| 1322 | } | ||
| 1323 | |||
| 1324 | static ssize_t mxt_pause_store(struct device *dev, | ||
| 1325 | struct device_attribute *attr, const char *buf, size_t count) | ||
| 1326 | { | ||
| 1327 | struct mxt_data *data = dev_get_drvdata(dev); | ||
| 1328 | int i; | ||
| 1329 | |||
| 1330 | if (sscanf(buf, "%u", &i) == 1 && i < 2) { | ||
| 1331 | data->driver_paused = i; | ||
| 1332 | |||
| 1333 | dev_dbg(dev, "%s\n", i ? "paused" : "unpaused"); | ||
| 1334 | } else { | ||
| 1335 | dev_dbg(dev, "pause_driver write error\n"); | ||
| 1336 | } | ||
| 1337 | return count; | ||
| 1338 | } | ||
| 1339 | |||
| 1340 | static ssize_t mxt_debug_enable_show(struct device *dev, | ||
| 1341 | struct device_attribute *attr, char *buf) | ||
| 1342 | { | ||
| 1343 | struct mxt_data *data = dev_get_drvdata(dev); | ||
| 1344 | int count = 0; | ||
| 1345 | |||
| 1346 | count += sprintf(buf + count, "%d", data->debug_enabled); | ||
| 1347 | count += sprintf(buf + count, "\n"); | ||
| 1348 | |||
| 1349 | return count; | ||
| 1350 | } | ||
| 1351 | |||
| 1352 | static ssize_t mxt_debug_enable_store(struct device *dev, | ||
| 1353 | struct device_attribute *attr, const char *buf, size_t count) | ||
| 1354 | { | ||
| 1355 | struct mxt_data *data = dev_get_drvdata(dev); | ||
| 1356 | int i; | ||
| 1357 | |||
| 1358 | if (sscanf(buf, "%u", &i) == 1 && i < 2) { | ||
| 1359 | data->debug_enabled = i; | ||
| 1360 | |||
| 1361 | dev_dbg(dev, "%s\n", i ? "debug enabled" : "debug disabled"); | ||
| 1362 | } else { | ||
| 1363 | dev_dbg(dev, "debug_enabled write error\n"); | ||
| 1364 | } | ||
| 1365 | return count; | ||
| 1366 | } | ||
| 1367 | |||
| 1368 | static ssize_t mxt_slowscan_show(struct device *dev, | ||
| 1369 | struct device_attribute *attr, char *buf) | ||
| 1370 | { | ||
| 1371 | struct mxt_data *data = dev_get_drvdata(dev); | ||
| 1372 | int count = 0; | ||
| 1373 | int error; | ||
| 1374 | u8 actv_cycle_time; | ||
| 1375 | u8 idle_cycle_time; | ||
| 1376 | u8 actv2idle_timeout; | ||
| 1377 | dev_info(dev, "Calling mxt_slowscan_show()\n"); | ||
| 1378 | |||
| 1379 | error = mxt_read_object(data, MXT_GEN_POWER_T7, | ||
| 1380 | MXT_POWER_ACTVACQINT, | ||
| 1381 | &actv_cycle_time); | ||
| 1382 | |||
| 1383 | if (error) | ||
| 1384 | return error; | ||
| 1385 | |||
| 1386 | error = mxt_read_object(data, MXT_GEN_POWER_T7, | ||
| 1387 | MXT_POWER_IDLEACQINT, | ||
| 1388 | &idle_cycle_time); | ||
| 1389 | |||
| 1390 | if (error) | ||
| 1391 | return error; | ||
| 1392 | |||
| 1393 | error = mxt_read_object(data, MXT_GEN_POWER_T7, | ||
| 1394 | MXT_POWER_ACTV2IDLETO, | ||
| 1395 | &actv2idle_timeout); | ||
| 1396 | |||
| 1397 | if (error) | ||
| 1398 | return error; | ||
| 1399 | |||
| 1400 | count += sprintf(buf + count, "SLOW SCAN (enable/disable) = %s.\n", data->slowscan_enabled ? "enabled" : "disabled"); | ||
| 1401 | count += sprintf(buf + count, "SLOW SCAN (actv_cycle_time) = %umS.\n", data->slowscan_actv_cycle_time); | ||
| 1402 | count += sprintf(buf + count, "SLOW SCAN (idle_cycle_time) = %umS.\n", data->slowscan_idle_cycle_time); | ||
| 1403 | count += sprintf(buf + count, "SLOW SCAN (actv2idle_timeout) = %u.%0uS.\n", data->slowscan_actv2idle_timeout / 10, \ | ||
| 1404 | data->slowscan_actv2idle_timeout % 10); | ||
| 1405 | count += sprintf(buf + count, "CURRENT (actv_cycle_time) = %umS.\n", actv_cycle_time); | ||
| 1406 | count += sprintf(buf + count, "CURRENT (idle_cycle_time) = %umS.\n", idle_cycle_time); | ||
| 1407 | count += sprintf(buf + count, "CURRENT (actv2idle_timeout) = %u.%0uS.\n", actv2idle_timeout / 10, \ | ||
| 1408 | actv2idle_timeout % 10); | ||
| 1409 | |||
| 1410 | return count; | ||
| 1411 | } | ||
| 1412 | |||
| 1413 | static ssize_t mxt_slowscan_store(struct device *dev, | ||
| 1414 | struct device_attribute *attr, const char *buf, size_t count) | ||
| 1415 | { | ||
| 1416 | struct mxt_data *data = dev_get_drvdata(dev); | ||
| 1417 | int fn; | ||
| 1418 | int val; | ||
| 1419 | int ret; | ||
| 1420 | |||
| 1421 | dev_info(dev, "Calling mxt_slowscan_store()\n"); | ||
| 1422 | ret = sscanf(buf, "%u %u", &fn, &val); | ||
| 1423 | if ((ret == 1) || (ret == 2)) { | ||
| 1424 | switch (fn) { | ||
| 1425 | case SLOSCAN_DISABLE: | ||
| 1426 | if (data->slowscan_enabled) { | ||
| 1427 | data->actv_cycle_time = data->slowscan_shad_actv_cycle_time; | ||
| 1428 | data->idle_cycle_time = data->slowscan_shad_idle_cycle_time; | ||
| 1429 | data->actv2idle_timeout = data->slowscan_shad_actv2idle_timeout; | ||
| 1430 | data->slowscan_enabled = 0; | ||
| 1431 | mxt_set_power_cfg(data, 0); | ||
| 1432 | } | ||
| 1433 | break; | ||
| 1434 | |||
| 1435 | case SLOSCAN_ENABLE: | ||
| 1436 | if (!data->slowscan_enabled) { | ||
| 1437 | data->slowscan_shad_actv_cycle_time = data->actv_cycle_time; | ||
| 1438 | data->slowscan_shad_idle_cycle_time = data->idle_cycle_time; | ||
| 1439 | data->slowscan_shad_actv2idle_timeout = data->actv2idle_timeout; | ||
| 1440 | data->actv_cycle_time = data->slowscan_actv_cycle_time; | ||
| 1441 | data->idle_cycle_time = data->slowscan_idle_cycle_time; | ||
| 1442 | data->actv2idle_timeout = data->slowscan_actv2idle_timeout; | ||
| 1443 | data->slowscan_enabled = 1; | ||
| 1444 | mxt_set_power_cfg(data, 0); | ||
| 1445 | } | ||
| 1446 | break; | ||
| 1447 | |||
| 1448 | case SLOSCAN_SET_ACTVACQINT: | ||
| 1449 | data->slowscan_actv_cycle_time = val; | ||
| 1450 | break; | ||
| 1451 | |||
| 1452 | case SLOSCAN_SET_IDLEACQINT: | ||
| 1453 | data->slowscan_idle_cycle_time = val; | ||
| 1454 | break; | ||
| 1455 | |||
| 1456 | case SLOSCAN_SET_ACTV2IDLETO: | ||
| 1457 | data->slowscan_actv2idle_timeout = val; | ||
| 1458 | break; | ||
| 1459 | } | ||
| 1460 | } | ||
| 1461 | return count; | ||
| 1462 | } | ||
| 1463 | |||
| 1464 | static ssize_t mxt_mem_access_read(struct file *filp, struct kobject *kobj, | ||
| 1465 | struct bin_attribute *bin_attr, char *buf, loff_t off, size_t count) | ||
| 1466 | { | ||
| 1467 | struct device *dev = container_of(kobj, struct device, kobj); | ||
| 1468 | struct mxt_data *data = dev_get_drvdata(dev); | ||
| 1469 | int ret = 0; | ||
| 1470 | |||
| 1471 | if (off >= 32768) | ||
| 1472 | return -EIO; | ||
| 1473 | |||
| 1474 | if (off + count > 32768) | ||
| 1475 | count = 32768 - off; | ||
| 1476 | |||
| 1477 | if (count > 256) | ||
| 1478 | count = 256; | ||
| 1479 | |||
| 1480 | if (count > 0) | ||
| 1481 | ret = __mxt_read_reg(data->client, off, count, buf); | ||
| 1482 | |||
| 1483 | return ret == 0 ? count : ret; | ||
| 1484 | } | ||
| 1485 | |||
| 1486 | int mxt_write_block(struct i2c_client *client, u16 addr, u16 length, u8 *value) | ||
| 1487 | { | ||
| 1488 | int i; | ||
| 1489 | struct { | ||
| 1490 | __le16 le_addr; | ||
| 1491 | u8 data[256]; | ||
| 1492 | } i2c_block_transfer; | ||
| 1493 | |||
| 1494 | if (length > 256) | ||
| 1495 | return -EINVAL; | ||
| 1496 | |||
| 1497 | i2c_get_clientdata(client); | ||
| 1498 | |||
| 1499 | for (i = 0; i < length; i++) | ||
| 1500 | i2c_block_transfer.data[i] = *value++; | ||
| 1501 | |||
| 1502 | i2c_block_transfer.le_addr = cpu_to_le16(addr); | ||
| 1503 | |||
| 1504 | i = i2c_master_send(client, (u8 *) &i2c_block_transfer, length + 2); | ||
| 1505 | |||
| 1506 | if (i == (length + 2)) | ||
| 1507 | return 0; | ||
| 1508 | else | ||
| 1509 | return -EIO; | ||
| 1510 | } | ||
| 1511 | |||
| 1512 | static ssize_t mxt_mem_access_write(struct file *filp, struct kobject *kobj, | ||
| 1513 | struct bin_attribute *bin_attr, char *buf, loff_t off, size_t count) | ||
| 1514 | { | ||
| 1515 | struct device *dev = container_of(kobj, struct device, kobj); | ||
| 1516 | struct mxt_data *data = dev_get_drvdata(dev); | ||
| 1517 | int ret = 0; | ||
| 1518 | |||
| 1519 | if (off >= 32768) | ||
| 1520 | return -EIO; | ||
| 1521 | |||
| 1522 | if (off + count > 32768) | ||
| 1523 | count = 32768 - off; | ||
| 1524 | |||
| 1525 | if (count > 256) | ||
| 1526 | count = 256; | ||
| 1527 | |||
| 1528 | if (count > 0) | ||
| 1529 | ret = mxt_write_block(data->client, off, count, buf); | ||
| 1530 | |||
| 1531 | return ret == 0 ? count : 0; | ||
| 1532 | } | ||
| 1533 | |||
| 1534 | static DEVICE_ATTR(object, 0444, mxt_object_show, NULL); | ||
| 1535 | static DEVICE_ATTR(update_fw, 0664, NULL, mxt_update_fw_store); | ||
| 1536 | static DEVICE_ATTR(pause_driver, 0664, mxt_pause_show, mxt_pause_store); | ||
| 1537 | static DEVICE_ATTR(debug_enable, 0664, mxt_debug_enable_show, mxt_debug_enable_store); | ||
| 1538 | static DEVICE_ATTR(slowscan_enable, 0664, mxt_slowscan_show, mxt_slowscan_store); | ||
| 1055 | 1539 | ||
| 1056 | static struct attribute *mxt_attrs[] = { | 1540 | static struct attribute *mxt_attrs[] = { |
| 1057 | &dev_attr_fw_version.attr, | ||
| 1058 | &dev_attr_hw_version.attr, | ||
| 1059 | &dev_attr_object.attr, | 1541 | &dev_attr_object.attr, |
| 1060 | &dev_attr_update_fw.attr, | 1542 | &dev_attr_update_fw.attr, |
| 1543 | &dev_attr_pause_driver.attr, | ||
| 1544 | &dev_attr_debug_enable.attr, | ||
| 1545 | &dev_attr_slowscan_enable.attr, | ||
| 1061 | NULL | 1546 | NULL |
| 1062 | }; | 1547 | }; |
| 1063 | 1548 | ||
| @@ -1067,16 +1552,54 @@ static const struct attribute_group mxt_attr_group = { | |||
| 1067 | 1552 | ||
| 1068 | static void mxt_start(struct mxt_data *data) | 1553 | static void mxt_start(struct mxt_data *data) |
| 1069 | { | 1554 | { |
| 1555 | int error = 0; | ||
| 1556 | int cnt; | ||
| 1557 | struct device *dev = &data->client->dev; | ||
| 1558 | |||
| 1559 | dev_info(dev, "mxt_start: is_stopped = %d\n", data->is_stopped); | ||
| 1560 | if (data->is_stopped == 0) | ||
| 1561 | return; | ||
| 1562 | |||
| 1070 | /* Touch enable */ | 1563 | /* Touch enable */ |
| 1071 | mxt_write_object(data, | 1564 | cnt = ARRAY_SIZE(mxt_save); |
| 1072 | MXT_TOUCH_MULTI_T9, MXT_TOUCH_CTRL, 0x83); | 1565 | while (cnt--) |
| 1566 | error |= mxt_write_object(data, mxt_save[cnt].suspend_obj, | ||
| 1567 | mxt_save[cnt].suspend_reg, | ||
| 1568 | mxt_save[cnt].restore_val); | ||
| 1569 | |||
| 1570 | if (!error) | ||
| 1571 | dev_info(dev, "MXT started\n"); | ||
| 1572 | |||
| 1573 | data->is_stopped = 0; | ||
| 1073 | } | 1574 | } |
| 1074 | 1575 | ||
| 1075 | static void mxt_stop(struct mxt_data *data) | 1576 | static void mxt_stop(struct mxt_data *data) |
| 1076 | { | 1577 | { |
| 1578 | int error = 0; | ||
| 1579 | int i, cnt; | ||
| 1580 | struct device *dev = &data->client->dev; | ||
| 1581 | |||
| 1582 | dev_info(dev, "mxt_stop: is_stopped = %d\n", data->is_stopped); | ||
| 1583 | if (data->is_stopped) | ||
| 1584 | return; | ||
| 1585 | |||
| 1077 | /* Touch disable */ | 1586 | /* Touch disable */ |
| 1078 | mxt_write_object(data, | 1587 | cnt = ARRAY_SIZE(mxt_save); |
| 1079 | MXT_TOUCH_MULTI_T9, MXT_TOUCH_CTRL, 0); | 1588 | for (i = 0; i < cnt; i++) { |
| 1589 | if (mxt_save[i].suspend_flags == MXT_SUSPEND_DYNAMIC) | ||
| 1590 | error |= mxt_read_object(data, | ||
| 1591 | mxt_save[i].suspend_obj, | ||
| 1592 | mxt_save[i].suspend_reg, | ||
| 1593 | &mxt_save[i].restore_val); | ||
| 1594 | error |= mxt_write_object(data, mxt_save[i].suspend_obj, | ||
| 1595 | mxt_save[i].suspend_reg, | ||
| 1596 | mxt_save[i].suspend_val); | ||
| 1597 | } | ||
| 1598 | |||
| 1599 | if (!error) | ||
| 1600 | dev_info(dev, "MXT suspended\n"); | ||
| 1601 | |||
| 1602 | data->is_stopped = 1; | ||
| 1080 | } | 1603 | } |
| 1081 | 1604 | ||
| 1082 | static int mxt_input_open(struct input_dev *dev) | 1605 | static int mxt_input_open(struct input_dev *dev) |
| @@ -1095,14 +1618,13 @@ static void mxt_input_close(struct input_dev *dev) | |||
| 1095 | mxt_stop(data); | 1618 | mxt_stop(data); |
| 1096 | } | 1619 | } |
| 1097 | 1620 | ||
| 1098 | static int mxt_probe(struct i2c_client *client, | 1621 | static int __devinit mxt_probe(struct i2c_client *client, |
| 1099 | const struct i2c_device_id *id) | 1622 | const struct i2c_device_id *id) |
| 1100 | { | 1623 | { |
| 1101 | const struct mxt_platform_data *pdata = client->dev.platform_data; | 1624 | const struct mxt_platform_data *pdata = client->dev.platform_data; |
| 1102 | struct mxt_data *data; | 1625 | struct mxt_data *data; |
| 1103 | struct input_dev *input_dev; | 1626 | struct input_dev *input_dev; |
| 1104 | int error; | 1627 | int error; |
| 1105 | unsigned int num_mt_slots; | ||
| 1106 | 1628 | ||
| 1107 | if (!pdata) | 1629 | if (!pdata) |
| 1108 | return -EINVAL; | 1630 | return -EINVAL; |
| @@ -1115,11 +1637,7 @@ static int mxt_probe(struct i2c_client *client, | |||
| 1115 | goto err_free_mem; | 1637 | goto err_free_mem; |
| 1116 | } | 1638 | } |
| 1117 | 1639 | ||
| 1118 | input_dev->name = "Atmel maXTouch Touchscreen"; | 1640 | input_dev->name = "atmel-maxtouch"; |
| 1119 | snprintf(data->phys, sizeof(data->phys), "i2c-%u-%04x/input0", | ||
| 1120 | client->adapter->nr, client->addr); | ||
| 1121 | input_dev->phys = data->phys; | ||
| 1122 | |||
| 1123 | input_dev->id.bustype = BUS_I2C; | 1641 | input_dev->id.bustype = BUS_I2C; |
| 1124 | input_dev->dev.parent = &client->dev; | 1642 | input_dev->dev.parent = &client->dev; |
| 1125 | input_dev->open = mxt_input_open; | 1643 | input_dev->open = mxt_input_open; |
| @@ -1129,13 +1647,10 @@ static int mxt_probe(struct i2c_client *client, | |||
| 1129 | data->input_dev = input_dev; | 1647 | data->input_dev = input_dev; |
| 1130 | data->pdata = pdata; | 1648 | data->pdata = pdata; |
| 1131 | data->irq = client->irq; | 1649 | data->irq = client->irq; |
| 1650 | data->is_stopped = 0; | ||
| 1132 | 1651 | ||
| 1133 | mxt_calc_resolution(data); | 1652 | mxt_calc_resolution(data); |
| 1134 | 1653 | ||
| 1135 | error = mxt_initialize(data); | ||
| 1136 | if (error) | ||
| 1137 | goto err_free_mem; | ||
| 1138 | |||
| 1139 | __set_bit(EV_ABS, input_dev->evbit); | 1654 | __set_bit(EV_ABS, input_dev->evbit); |
| 1140 | __set_bit(EV_KEY, input_dev->evbit); | 1655 | __set_bit(EV_KEY, input_dev->evbit); |
| 1141 | __set_bit(BTN_TOUCH, input_dev->keybit); | 1656 | __set_bit(BTN_TOUCH, input_dev->keybit); |
| @@ -1149,10 +1664,6 @@ static int mxt_probe(struct i2c_client *client, | |||
| 1149 | 0, 255, 0, 0); | 1664 | 0, 255, 0, 0); |
| 1150 | 1665 | ||
| 1151 | /* For multi touch */ | 1666 | /* For multi touch */ |
| 1152 | num_mt_slots = data->T9_reportid_max - data->T9_reportid_min + 1; | ||
| 1153 | error = input_mt_init_slots(input_dev, num_mt_slots, 0); | ||
| 1154 | if (error) | ||
| 1155 | goto err_free_object; | ||
| 1156 | input_set_abs_params(input_dev, ABS_MT_TOUCH_MAJOR, | 1667 | input_set_abs_params(input_dev, ABS_MT_TOUCH_MAJOR, |
| 1157 | 0, MXT_MAX_AREA, 0, 0); | 1668 | 0, MXT_MAX_AREA, 0, 0); |
| 1158 | input_set_abs_params(input_dev, ABS_MT_POSITION_X, | 1669 | input_set_abs_params(input_dev, ABS_MT_POSITION_X, |
| @@ -1165,25 +1676,55 @@ static int mxt_probe(struct i2c_client *client, | |||
| 1165 | input_set_drvdata(input_dev, data); | 1676 | input_set_drvdata(input_dev, data); |
| 1166 | i2c_set_clientdata(client, data); | 1677 | i2c_set_clientdata(client, data); |
| 1167 | 1678 | ||
| 1679 | mutex_init(&data->access_mutex); | ||
| 1680 | |||
| 1681 | error = mxt_initialize(data); | ||
| 1682 | if (error) | ||
| 1683 | goto err_free_object; | ||
| 1684 | |||
| 1168 | error = request_threaded_irq(client->irq, NULL, mxt_interrupt, | 1685 | error = request_threaded_irq(client->irq, NULL, mxt_interrupt, |
| 1169 | pdata->irqflags | IRQF_ONESHOT, | 1686 | pdata->irqflags, client->dev.driver->name, data); |
| 1170 | client->name, data); | ||
| 1171 | if (error) { | 1687 | if (error) { |
| 1172 | dev_err(&client->dev, "Failed to register interrupt\n"); | 1688 | dev_err(&client->dev, "Failed to register interrupt\n"); |
| 1173 | goto err_free_object; | 1689 | goto err_free_object; |
| 1174 | } | 1690 | } |
| 1175 | 1691 | ||
| 1692 | #if defined(CONFIG_HAS_EARLYSUSPEND) | ||
| 1693 | data->early_suspend.level = EARLY_SUSPEND_LEVEL_BLANK_SCREEN + 1; | ||
| 1694 | data->early_suspend.suspend = mxt_early_suspend; | ||
| 1695 | data->early_suspend.resume = mxt_early_resume; | ||
| 1696 | register_early_suspend(&data->early_suspend); | ||
| 1697 | #endif | ||
| 1698 | |||
| 1176 | error = mxt_make_highchg(data); | 1699 | error = mxt_make_highchg(data); |
| 1177 | if (error) | 1700 | if (error) { |
| 1701 | dev_err(&client->dev, "Failed to make high CHG\n"); | ||
| 1178 | goto err_free_irq; | 1702 | goto err_free_irq; |
| 1703 | } | ||
| 1179 | 1704 | ||
| 1180 | error = input_register_device(input_dev); | 1705 | error = input_register_device(input_dev); |
| 1181 | if (error) | 1706 | if (error) { |
| 1707 | dev_err(&client->dev, "Failed to register input device\n"); | ||
| 1182 | goto err_free_irq; | 1708 | goto err_free_irq; |
| 1709 | } | ||
| 1183 | 1710 | ||
| 1184 | error = sysfs_create_group(&client->dev.kobj, &mxt_attr_group); | 1711 | error = sysfs_create_group(&client->dev.kobj, &mxt_attr_group); |
| 1185 | if (error) | 1712 | if (error) { |
| 1713 | dev_err(&client->dev, "Failed to create sysfs group\n"); | ||
| 1714 | goto err_unregister_device; | ||
| 1715 | } | ||
| 1716 | |||
| 1717 | sysfs_bin_attr_init(&data->mem_access_attr); | ||
| 1718 | data->mem_access_attr.attr.name = "mem_access"; | ||
| 1719 | data->mem_access_attr.attr.mode = S_IRUGO | S_IWUSR | S_IWGRP; | ||
| 1720 | data->mem_access_attr.read = mxt_mem_access_read; | ||
| 1721 | data->mem_access_attr.write = mxt_mem_access_write; | ||
| 1722 | data->mem_access_attr.size = 65535; | ||
| 1723 | |||
| 1724 | if (sysfs_create_bin_file(&client->dev.kobj, &data->mem_access_attr) < 0) { | ||
| 1725 | dev_err(&client->dev, "Failed to create %s\n", data->mem_access_attr.attr.name); | ||
| 1186 | goto err_unregister_device; | 1726 | goto err_unregister_device; |
| 1727 | } | ||
| 1187 | 1728 | ||
| 1188 | return 0; | 1729 | return 0; |
| 1189 | 1730 | ||
| @@ -1200,10 +1741,11 @@ err_free_mem: | |||
| 1200 | return error; | 1741 | return error; |
| 1201 | } | 1742 | } |
| 1202 | 1743 | ||
| 1203 | static int mxt_remove(struct i2c_client *client) | 1744 | static int __devexit mxt_remove(struct i2c_client *client) |
| 1204 | { | 1745 | { |
| 1205 | struct mxt_data *data = i2c_get_clientdata(client); | 1746 | struct mxt_data *data = i2c_get_clientdata(client); |
| 1206 | 1747 | ||
| 1748 | sysfs_remove_bin_file(&client->dev.kobj, &data->mem_access_attr); | ||
| 1207 | sysfs_remove_group(&client->dev.kobj, &mxt_attr_group); | 1749 | sysfs_remove_group(&client->dev.kobj, &mxt_attr_group); |
| 1208 | free_irq(data->irq, data); | 1750 | free_irq(data->irq, data); |
| 1209 | input_unregister_device(data->input_dev); | 1751 | input_unregister_device(data->input_dev); |
| @@ -1213,7 +1755,7 @@ static int mxt_remove(struct i2c_client *client) | |||
| 1213 | return 0; | 1755 | return 0; |
| 1214 | } | 1756 | } |
| 1215 | 1757 | ||
| 1216 | #ifdef CONFIG_PM_SLEEP | 1758 | #ifdef CONFIG_PM |
| 1217 | static int mxt_suspend(struct device *dev) | 1759 | static int mxt_suspend(struct device *dev) |
| 1218 | { | 1760 | { |
| 1219 | struct i2c_client *client = to_i2c_client(dev); | 1761 | struct i2c_client *client = to_i2c_client(dev); |
| @@ -1237,8 +1779,7 @@ static int mxt_resume(struct device *dev) | |||
| 1237 | struct input_dev *input_dev = data->input_dev; | 1779 | struct input_dev *input_dev = data->input_dev; |
| 1238 | 1780 | ||
| 1239 | /* Soft reset */ | 1781 | /* Soft reset */ |
| 1240 | mxt_write_object(data, MXT_GEN_COMMAND_T6, | 1782 | mxt_write_object(data, MXT_GEN_COMMAND_T6, MXT_COMMAND_RESET, 1); |
| 1241 | MXT_COMMAND_RESET, 1); | ||
| 1242 | 1783 | ||
| 1243 | msleep(MXT_RESET_TIME); | 1784 | msleep(MXT_RESET_TIME); |
| 1244 | 1785 | ||
| @@ -1251,9 +1792,40 @@ static int mxt_resume(struct device *dev) | |||
| 1251 | 1792 | ||
| 1252 | return 0; | 1793 | return 0; |
| 1253 | } | 1794 | } |
| 1254 | #endif | ||
| 1255 | 1795 | ||
| 1256 | static SIMPLE_DEV_PM_OPS(mxt_pm_ops, mxt_suspend, mxt_resume); | 1796 | #if defined(CONFIG_HAS_EARLYSUSPEND) |
| 1797 | static void mxt_early_suspend(struct early_suspend *es) | ||
| 1798 | { | ||
| 1799 | struct mxt_data *mxt; | ||
| 1800 | struct device *dev; | ||
| 1801 | mxt = container_of(es, struct mxt_data, early_suspend); | ||
| 1802 | dev = &mxt->client->dev; | ||
| 1803 | dev_info(dev, "MXT Early Suspend entered\n"); | ||
| 1804 | |||
| 1805 | if (mxt_suspend(&mxt->client->dev) != 0) | ||
| 1806 | dev_err(&mxt->client->dev, "%s: failed\n", __func__); | ||
| 1807 | dev_info(dev, "MXT Early Suspended\n"); | ||
| 1808 | } | ||
| 1809 | |||
| 1810 | static void mxt_early_resume(struct early_suspend *es) | ||
| 1811 | { | ||
| 1812 | struct mxt_data *mxt; | ||
| 1813 | struct device *dev; | ||
| 1814 | mxt = container_of(es, struct mxt_data, early_suspend); | ||
| 1815 | dev = &mxt->client->dev; | ||
| 1816 | dev_info(dev, "MXT Early Resume entered\n"); | ||
| 1817 | |||
| 1818 | if (mxt_resume(&mxt->client->dev) != 0) | ||
| 1819 | dev_err(&mxt->client->dev, "%s: failed\n", __func__); | ||
| 1820 | dev_info(dev, "MXT Early Resumed\n"); | ||
| 1821 | } | ||
| 1822 | #else | ||
| 1823 | static const struct dev_pm_ops mxt_pm_ops = { | ||
| 1824 | .suspend = mxt_suspend, | ||
| 1825 | .resume = mxt_resume, | ||
| 1826 | }; | ||
| 1827 | #endif | ||
| 1828 | #endif | ||
| 1257 | 1829 | ||
| 1258 | static const struct i2c_device_id mxt_id[] = { | 1830 | static const struct i2c_device_id mxt_id[] = { |
| 1259 | { "qt602240_ts", 0 }, | 1831 | { "qt602240_ts", 0 }, |
| @@ -1267,14 +1839,27 @@ static struct i2c_driver mxt_driver = { | |||
| 1267 | .driver = { | 1839 | .driver = { |
| 1268 | .name = "atmel_mxt_ts", | 1840 | .name = "atmel_mxt_ts", |
| 1269 | .owner = THIS_MODULE, | 1841 | .owner = THIS_MODULE, |
| 1842 | #if defined(CONFIG_PM) && !defined(CONFIG_HAS_EARLYSUSPEND) | ||
| 1270 | .pm = &mxt_pm_ops, | 1843 | .pm = &mxt_pm_ops, |
| 1844 | #endif | ||
| 1271 | }, | 1845 | }, |
| 1272 | .probe = mxt_probe, | 1846 | .probe = mxt_probe, |
| 1273 | .remove = mxt_remove, | 1847 | .remove = __devexit_p(mxt_remove), |
| 1274 | .id_table = mxt_id, | 1848 | .id_table = mxt_id, |
| 1275 | }; | 1849 | }; |
| 1276 | 1850 | ||
| 1277 | module_i2c_driver(mxt_driver); | 1851 | static int __init mxt_init(void) |
| 1852 | { | ||
| 1853 | return i2c_add_driver(&mxt_driver); | ||
| 1854 | } | ||
| 1855 | |||
| 1856 | static void __exit mxt_exit(void) | ||
| 1857 | { | ||
| 1858 | i2c_del_driver(&mxt_driver); | ||
| 1859 | } | ||
| 1860 | |||
| 1861 | module_init(mxt_init); | ||
| 1862 | module_exit(mxt_exit); | ||
| 1278 | 1863 | ||
| 1279 | /* Module information */ | 1864 | /* Module information */ |
| 1280 | MODULE_AUTHOR("Joonyoung Shim <jy0922.shim@samsung.com>"); | 1865 | MODULE_AUTHOR("Joonyoung Shim <jy0922.shim@samsung.com>"); |
diff --git a/drivers/input/touchscreen/atmel_tsadcc.c b/drivers/input/touchscreen/atmel_tsadcc.c index 95f6785a94b..432c69be6ac 100644 --- a/drivers/input/touchscreen/atmel_tsadcc.c +++ b/drivers/input/touchscreen/atmel_tsadcc.c | |||
| @@ -22,7 +22,7 @@ | |||
| 22 | #include <linux/clk.h> | 22 | #include <linux/clk.h> |
| 23 | #include <linux/platform_device.h> | 23 | #include <linux/platform_device.h> |
| 24 | #include <linux/io.h> | 24 | #include <linux/io.h> |
| 25 | #include <linux/platform_data/atmel.h> | 25 | #include <mach/board.h> |
| 26 | #include <mach/cpu.h> | 26 | #include <mach/cpu.h> |
| 27 | 27 | ||
| 28 | /* Register definitions based on AT91SAM9RL64 preliminary draft datasheet */ | 28 | /* Register definitions based on AT91SAM9RL64 preliminary draft datasheet */ |
| @@ -177,7 +177,7 @@ static irqreturn_t atmel_tsadcc_interrupt(int irq, void *dev) | |||
| 177 | * The functions for inserting/removing us as a module. | 177 | * The functions for inserting/removing us as a module. |
| 178 | */ | 178 | */ |
| 179 | 179 | ||
| 180 | static int atmel_tsadcc_probe(struct platform_device *pdev) | 180 | static int __devinit atmel_tsadcc_probe(struct platform_device *pdev) |
| 181 | { | 181 | { |
| 182 | struct atmel_tsadcc *ts_dev; | 182 | struct atmel_tsadcc *ts_dev; |
| 183 | struct input_dev *input_dev; | 183 | struct input_dev *input_dev; |
| @@ -229,7 +229,7 @@ static int atmel_tsadcc_probe(struct platform_device *pdev) | |||
| 229 | goto err_release_mem; | 229 | goto err_release_mem; |
| 230 | } | 230 | } |
| 231 | 231 | ||
| 232 | err = request_irq(ts_dev->irq, atmel_tsadcc_interrupt, 0, | 232 | err = request_irq(ts_dev->irq, atmel_tsadcc_interrupt, IRQF_DISABLED, |
| 233 | pdev->dev.driver->name, ts_dev); | 233 | pdev->dev.driver->name, ts_dev); |
| 234 | if (err) { | 234 | if (err) { |
| 235 | dev_err(&pdev->dev, "failed to allocate irq.\n"); | 235 | dev_err(&pdev->dev, "failed to allocate irq.\n"); |
| @@ -323,7 +323,7 @@ err_free_mem: | |||
| 323 | return err; | 323 | return err; |
| 324 | } | 324 | } |
| 325 | 325 | ||
| 326 | static int atmel_tsadcc_remove(struct platform_device *pdev) | 326 | static int __devexit atmel_tsadcc_remove(struct platform_device *pdev) |
| 327 | { | 327 | { |
| 328 | struct atmel_tsadcc *ts_dev = dev_get_drvdata(&pdev->dev); | 328 | struct atmel_tsadcc *ts_dev = dev_get_drvdata(&pdev->dev); |
| 329 | struct resource *res; | 329 | struct resource *res; |
| @@ -346,12 +346,25 @@ static int atmel_tsadcc_remove(struct platform_device *pdev) | |||
| 346 | 346 | ||
| 347 | static struct platform_driver atmel_tsadcc_driver = { | 347 | static struct platform_driver atmel_tsadcc_driver = { |
| 348 | .probe = atmel_tsadcc_probe, | 348 | .probe = atmel_tsadcc_probe, |
| 349 | .remove = atmel_tsadcc_remove, | 349 | .remove = __devexit_p(atmel_tsadcc_remove), |
| 350 | .driver = { | 350 | .driver = { |
| 351 | .name = "atmel_tsadcc", | 351 | .name = "atmel_tsadcc", |
| 352 | }, | 352 | }, |
| 353 | }; | 353 | }; |
| 354 | module_platform_driver(atmel_tsadcc_driver); | 354 | |
| 355 | static int __init atmel_tsadcc_init(void) | ||
| 356 | { | ||
| 357 | return platform_driver_register(&atmel_tsadcc_driver); | ||
| 358 | } | ||
| 359 | |||
| 360 | static void __exit atmel_tsadcc_exit(void) | ||
| 361 | { | ||
| 362 | platform_driver_unregister(&atmel_tsadcc_driver); | ||
| 363 | } | ||
| 364 | |||
| 365 | module_init(atmel_tsadcc_init); | ||
| 366 | module_exit(atmel_tsadcc_exit); | ||
| 367 | |||
| 355 | 368 | ||
| 356 | MODULE_LICENSE("GPL"); | 369 | MODULE_LICENSE("GPL"); |
| 357 | MODULE_DESCRIPTION("Atmel TouchScreen Driver"); | 370 | MODULE_DESCRIPTION("Atmel TouchScreen Driver"); |
diff --git a/drivers/input/touchscreen/auo-pixcir-ts.c b/drivers/input/touchscreen/auo-pixcir-ts.c deleted file mode 100644 index c6e19a96348..00000000000 --- a/drivers/input/touchscreen/auo-pixcir-ts.c +++ /dev/null | |||
| @@ -1,642 +0,0 @@ | |||
| 1 | /* | ||
| 2 | * Driver for AUO in-cell touchscreens | ||
| 3 | * | ||
| 4 | * Copyright (c) 2011 Heiko Stuebner <heiko@sntech.de> | ||
| 5 | * | ||
| 6 | * loosely based on auo_touch.c from Dell Streak vendor-kernel | ||
| 7 | * | ||
| 8 | * Copyright (c) 2008 QUALCOMM Incorporated. | ||
| 9 | * Copyright (c) 2008 QUALCOMM USA, INC. | ||
| 10 | * | ||
| 11 | * | ||
| 12 | * This software is licensed under the terms of the GNU General Public | ||
| 13 | * License version 2, as published by the Free Software Foundation, and | ||
| 14 | * may be copied, distributed, and modified under those terms. | ||
| 15 | * | ||
| 16 | * This program is distributed in the hope that it will be useful, | ||
| 17 | * but WITHOUT ANY WARRANTY; without even the implied warranty of | ||
| 18 | * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the | ||
| 19 | * GNU General Public License for more details. | ||
| 20 | * | ||
| 21 | */ | ||
| 22 | |||
| 23 | #include <linux/kernel.h> | ||
| 24 | #include <linux/module.h> | ||
| 25 | #include <linux/interrupt.h> | ||
| 26 | #include <linux/slab.h> | ||
| 27 | #include <linux/input.h> | ||
| 28 | #include <linux/jiffies.h> | ||
| 29 | #include <linux/i2c.h> | ||
| 30 | #include <linux/mutex.h> | ||
| 31 | #include <linux/delay.h> | ||
| 32 | #include <linux/gpio.h> | ||
| 33 | #include <linux/input/auo-pixcir-ts.h> | ||
| 34 | |||
| 35 | /* | ||
| 36 | * Coordinate calculation: | ||
| 37 | * X1 = X1_LSB + X1_MSB*256 | ||
| 38 | * Y1 = Y1_LSB + Y1_MSB*256 | ||
| 39 | * X2 = X2_LSB + X2_MSB*256 | ||
| 40 | * Y2 = Y2_LSB + Y2_MSB*256 | ||
| 41 | */ | ||
| 42 | #define AUO_PIXCIR_REG_X1_LSB 0x00 | ||
| 43 | #define AUO_PIXCIR_REG_X1_MSB 0x01 | ||
| 44 | #define AUO_PIXCIR_REG_Y1_LSB 0x02 | ||
| 45 | #define AUO_PIXCIR_REG_Y1_MSB 0x03 | ||
| 46 | #define AUO_PIXCIR_REG_X2_LSB 0x04 | ||
| 47 | #define AUO_PIXCIR_REG_X2_MSB 0x05 | ||
| 48 | #define AUO_PIXCIR_REG_Y2_LSB 0x06 | ||
| 49 | #define AUO_PIXCIR_REG_Y2_MSB 0x07 | ||
| 50 | |||
| 51 | #define AUO_PIXCIR_REG_STRENGTH 0x0d | ||
| 52 | #define AUO_PIXCIR_REG_STRENGTH_X1_LSB 0x0e | ||
| 53 | #define AUO_PIXCIR_REG_STRENGTH_X1_MSB 0x0f | ||
| 54 | |||
| 55 | #define AUO_PIXCIR_REG_RAW_DATA_X 0x2b | ||
| 56 | #define AUO_PIXCIR_REG_RAW_DATA_Y 0x4f | ||
| 57 | |||
| 58 | #define AUO_PIXCIR_REG_X_SENSITIVITY 0x6f | ||
| 59 | #define AUO_PIXCIR_REG_Y_SENSITIVITY 0x70 | ||
| 60 | #define AUO_PIXCIR_REG_INT_SETTING 0x71 | ||
| 61 | #define AUO_PIXCIR_REG_INT_WIDTH 0x72 | ||
| 62 | #define AUO_PIXCIR_REG_POWER_MODE 0x73 | ||
| 63 | |||
| 64 | #define AUO_PIXCIR_REG_VERSION 0x77 | ||
| 65 | #define AUO_PIXCIR_REG_CALIBRATE 0x78 | ||
| 66 | |||
| 67 | #define AUO_PIXCIR_REG_TOUCHAREA_X1 0x1e | ||
| 68 | #define AUO_PIXCIR_REG_TOUCHAREA_Y1 0x1f | ||
| 69 | #define AUO_PIXCIR_REG_TOUCHAREA_X2 0x20 | ||
| 70 | #define AUO_PIXCIR_REG_TOUCHAREA_Y2 0x21 | ||
| 71 | |||
| 72 | #define AUO_PIXCIR_REG_EEPROM_CALIB_X 0x42 | ||
| 73 | #define AUO_PIXCIR_REG_EEPROM_CALIB_Y 0xad | ||
| 74 | |||
| 75 | #define AUO_PIXCIR_INT_TPNUM_MASK 0xe0 | ||
| 76 | #define AUO_PIXCIR_INT_TPNUM_SHIFT 5 | ||
| 77 | #define AUO_PIXCIR_INT_RELEASE (1 << 4) | ||
| 78 | #define AUO_PIXCIR_INT_ENABLE (1 << 3) | ||
| 79 | #define AUO_PIXCIR_INT_POL_HIGH (1 << 2) | ||
| 80 | #define AUO_PIXCIR_INT_MODE_MASK 0x03 | ||
| 81 | |||
| 82 | /* | ||
| 83 | * Power modes: | ||
| 84 | * active: scan speed 60Hz | ||
| 85 | * sleep: scan speed 10Hz can be auto-activated, wakeup on 1st touch | ||
| 86 | * deep sleep: scan speed 1Hz can only be entered or left manually. | ||
| 87 | */ | ||
| 88 | #define AUO_PIXCIR_POWER_ACTIVE 0x00 | ||
| 89 | #define AUO_PIXCIR_POWER_SLEEP 0x01 | ||
| 90 | #define AUO_PIXCIR_POWER_DEEP_SLEEP 0x02 | ||
| 91 | #define AUO_PIXCIR_POWER_MASK 0x03 | ||
| 92 | |||
| 93 | #define AUO_PIXCIR_POWER_ALLOW_SLEEP (1 << 2) | ||
| 94 | #define AUO_PIXCIR_POWER_IDLE_TIME(ms) ((ms & 0xf) << 4) | ||
| 95 | |||
| 96 | #define AUO_PIXCIR_CALIBRATE 0x03 | ||
| 97 | |||
| 98 | #define AUO_PIXCIR_EEPROM_CALIB_X_LEN 62 | ||
| 99 | #define AUO_PIXCIR_EEPROM_CALIB_Y_LEN 36 | ||
| 100 | |||
| 101 | #define AUO_PIXCIR_RAW_DATA_X_LEN 18 | ||
| 102 | #define AUO_PIXCIR_RAW_DATA_Y_LEN 11 | ||
| 103 | |||
| 104 | #define AUO_PIXCIR_STRENGTH_ENABLE (1 << 0) | ||
| 105 | |||
| 106 | /* Touchscreen absolute values */ | ||
| 107 | #define AUO_PIXCIR_REPORT_POINTS 2 | ||
| 108 | #define AUO_PIXCIR_MAX_AREA 0xff | ||
| 109 | #define AUO_PIXCIR_PENUP_TIMEOUT_MS 10 | ||
| 110 | |||
| 111 | struct auo_pixcir_ts { | ||
| 112 | struct i2c_client *client; | ||
| 113 | struct input_dev *input; | ||
| 114 | char phys[32]; | ||
| 115 | |||
| 116 | /* special handling for touch_indicate interupt mode */ | ||
| 117 | bool touch_ind_mode; | ||
| 118 | |||
| 119 | wait_queue_head_t wait; | ||
| 120 | bool stopped; | ||
| 121 | }; | ||
| 122 | |||
| 123 | struct auo_point_t { | ||
| 124 | int coord_x; | ||
| 125 | int coord_y; | ||
| 126 | int area_major; | ||
| 127 | int area_minor; | ||
| 128 | int orientation; | ||
| 129 | }; | ||
| 130 | |||
| 131 | static int auo_pixcir_collect_data(struct auo_pixcir_ts *ts, | ||
| 132 | struct auo_point_t *point) | ||
| 133 | { | ||
| 134 | struct i2c_client *client = ts->client; | ||
| 135 | const struct auo_pixcir_ts_platdata *pdata = client->dev.platform_data; | ||
| 136 | uint8_t raw_coord[8]; | ||
| 137 | uint8_t raw_area[4]; | ||
| 138 | int i, ret; | ||
| 139 | |||
| 140 | /* touch coordinates */ | ||
| 141 | ret = i2c_smbus_read_i2c_block_data(client, AUO_PIXCIR_REG_X1_LSB, | ||
| 142 | 8, raw_coord); | ||
| 143 | if (ret < 0) { | ||
| 144 | dev_err(&client->dev, "failed to read coordinate, %d\n", ret); | ||
| 145 | return ret; | ||
| 146 | } | ||
| 147 | |||
| 148 | /* touch area */ | ||
| 149 | ret = i2c_smbus_read_i2c_block_data(client, AUO_PIXCIR_REG_TOUCHAREA_X1, | ||
| 150 | 4, raw_area); | ||
| 151 | if (ret < 0) { | ||
| 152 | dev_err(&client->dev, "could not read touch area, %d\n", ret); | ||
| 153 | return ret; | ||
| 154 | } | ||
| 155 | |||
| 156 | for (i = 0; i < AUO_PIXCIR_REPORT_POINTS; i++) { | ||
| 157 | point[i].coord_x = | ||
| 158 | raw_coord[4 * i + 1] << 8 | raw_coord[4 * i]; | ||
| 159 | point[i].coord_y = | ||
| 160 | raw_coord[4 * i + 3] << 8 | raw_coord[4 * i + 2]; | ||
| 161 | |||
| 162 | if (point[i].coord_x > pdata->x_max || | ||
| 163 | point[i].coord_y > pdata->y_max) { | ||
| 164 | dev_warn(&client->dev, "coordinates (%d,%d) invalid\n", | ||
| 165 | point[i].coord_x, point[i].coord_y); | ||
| 166 | point[i].coord_x = point[i].coord_y = 0; | ||
| 167 | } | ||
| 168 | |||
| 169 | /* determine touch major, minor and orientation */ | ||
| 170 | point[i].area_major = max(raw_area[2 * i], raw_area[2 * i + 1]); | ||
| 171 | point[i].area_minor = min(raw_area[2 * i], raw_area[2 * i + 1]); | ||
| 172 | point[i].orientation = raw_area[2 * i] > raw_area[2 * i + 1]; | ||
| 173 | } | ||
| 174 | |||
| 175 | return 0; | ||
| 176 | } | ||
| 177 | |||
| 178 | static irqreturn_t auo_pixcir_interrupt(int irq, void *dev_id) | ||
| 179 | { | ||
| 180 | struct auo_pixcir_ts *ts = dev_id; | ||
| 181 | struct i2c_client *client = ts->client; | ||
| 182 | const struct auo_pixcir_ts_platdata *pdata = client->dev.platform_data; | ||
| 183 | struct auo_point_t point[AUO_PIXCIR_REPORT_POINTS]; | ||
| 184 | int i; | ||
| 185 | int ret; | ||
| 186 | int fingers = 0; | ||
| 187 | int abs = -1; | ||
| 188 | |||
| 189 | while (!ts->stopped) { | ||
| 190 | |||
| 191 | /* check for up event in touch touch_ind_mode */ | ||
| 192 | if (ts->touch_ind_mode) { | ||
| 193 | if (gpio_get_value(pdata->gpio_int) == 0) { | ||
| 194 | input_mt_sync(ts->input); | ||
| 195 | input_report_key(ts->input, BTN_TOUCH, 0); | ||
| 196 | input_sync(ts->input); | ||
| 197 | break; | ||
| 198 | } | ||
| 199 | } | ||
| 200 | |||
| 201 | ret = auo_pixcir_collect_data(ts, point); | ||
| 202 | if (ret < 0) { | ||
| 203 | /* we want to loop only in touch_ind_mode */ | ||
| 204 | if (!ts->touch_ind_mode) | ||
| 205 | break; | ||
| 206 | |||
| 207 | wait_event_timeout(ts->wait, ts->stopped, | ||
| 208 | msecs_to_jiffies(AUO_PIXCIR_PENUP_TIMEOUT_MS)); | ||
| 209 | continue; | ||
| 210 | } | ||
| 211 | |||
| 212 | for (i = 0; i < AUO_PIXCIR_REPORT_POINTS; i++) { | ||
| 213 | if (point[i].coord_x > 0 || point[i].coord_y > 0) { | ||
| 214 | input_report_abs(ts->input, ABS_MT_POSITION_X, | ||
| 215 | point[i].coord_x); | ||
| 216 | input_report_abs(ts->input, ABS_MT_POSITION_Y, | ||
| 217 | point[i].coord_y); | ||
| 218 | input_report_abs(ts->input, ABS_MT_TOUCH_MAJOR, | ||
| 219 | point[i].area_major); | ||
| 220 | input_report_abs(ts->input, ABS_MT_TOUCH_MINOR, | ||
| 221 | point[i].area_minor); | ||
| 222 | input_report_abs(ts->input, ABS_MT_ORIENTATION, | ||
| 223 | point[i].orientation); | ||
| 224 | input_mt_sync(ts->input); | ||
| 225 | |||
| 226 | /* use first finger as source for singletouch */ | ||
| 227 | if (fingers == 0) | ||
| 228 | abs = i; | ||
| 229 | |||
| 230 | /* number of touch points could also be queried | ||
| 231 | * via i2c but would require an additional call | ||
| 232 | */ | ||
| 233 | fingers++; | ||
| 234 | } | ||
| 235 | } | ||
| 236 | |||
| 237 | input_report_key(ts->input, BTN_TOUCH, fingers > 0); | ||
| 238 | |||
| 239 | if (abs > -1) { | ||
| 240 | input_report_abs(ts->input, ABS_X, point[abs].coord_x); | ||
| 241 | input_report_abs(ts->input, ABS_Y, point[abs].coord_y); | ||
| 242 | } | ||
| 243 | |||
| 244 | input_sync(ts->input); | ||
| 245 | |||
| 246 | /* we want to loop only in touch_ind_mode */ | ||
| 247 | if (!ts->touch_ind_mode) | ||
| 248 | break; | ||
| 249 | |||
| 250 | wait_event_timeout(ts->wait, ts->stopped, | ||
| 251 | msecs_to_jiffies(AUO_PIXCIR_PENUP_TIMEOUT_MS)); | ||
| 252 | } | ||
| 253 | |||
| 254 | return IRQ_HANDLED; | ||
| 255 | } | ||
| 256 | |||
| 257 | /* | ||
| 258 | * Set the power mode of the device. | ||
| 259 | * Valid modes are | ||
| 260 | * - AUO_PIXCIR_POWER_ACTIVE | ||
| 261 | * - AUO_PIXCIR_POWER_SLEEP - automatically left on first touch | ||
| 262 | * - AUO_PIXCIR_POWER_DEEP_SLEEP | ||
| 263 | */ | ||
| 264 | static int auo_pixcir_power_mode(struct auo_pixcir_ts *ts, int mode) | ||
| 265 | { | ||
| 266 | struct i2c_client *client = ts->client; | ||
| 267 | int ret; | ||
| 268 | |||
| 269 | ret = i2c_smbus_read_byte_data(client, AUO_PIXCIR_REG_POWER_MODE); | ||
| 270 | if (ret < 0) { | ||
| 271 | dev_err(&client->dev, "unable to read reg %Xh, %d\n", | ||
| 272 | AUO_PIXCIR_REG_POWER_MODE, ret); | ||
| 273 | return ret; | ||
| 274 | } | ||
| 275 | |||
| 276 | ret &= ~AUO_PIXCIR_POWER_MASK; | ||
| 277 | ret |= mode; | ||
| 278 | |||
| 279 | ret = i2c_smbus_write_byte_data(client, AUO_PIXCIR_REG_POWER_MODE, ret); | ||
| 280 | if (ret) { | ||
| 281 | dev_err(&client->dev, "unable to write reg %Xh, %d\n", | ||
| 282 | AUO_PIXCIR_REG_POWER_MODE, ret); | ||
| 283 | return ret; | ||
| 284 | } | ||
| 285 | |||
| 286 | return 0; | ||
| 287 | } | ||
| 288 | |||
| 289 | static int auo_pixcir_int_config(struct auo_pixcir_ts *ts, | ||
| 290 | int int_setting) | ||
| 291 | { | ||
| 292 | struct i2c_client *client = ts->client; | ||
| 293 | struct auo_pixcir_ts_platdata *pdata = client->dev.platform_data; | ||
| 294 | int ret; | ||
| 295 | |||
| 296 | ret = i2c_smbus_read_byte_data(client, AUO_PIXCIR_REG_INT_SETTING); | ||
| 297 | if (ret < 0) { | ||
| 298 | dev_err(&client->dev, "unable to read reg %Xh, %d\n", | ||
| 299 | AUO_PIXCIR_REG_INT_SETTING, ret); | ||
| 300 | return ret; | ||
| 301 | } | ||
| 302 | |||
| 303 | ret &= ~AUO_PIXCIR_INT_MODE_MASK; | ||
| 304 | ret |= int_setting; | ||
| 305 | ret |= AUO_PIXCIR_INT_POL_HIGH; /* always use high for interrupts */ | ||
| 306 | |||
| 307 | ret = i2c_smbus_write_byte_data(client, AUO_PIXCIR_REG_INT_SETTING, | ||
| 308 | ret); | ||
| 309 | if (ret < 0) { | ||
| 310 | dev_err(&client->dev, "unable to write reg %Xh, %d\n", | ||
| 311 | AUO_PIXCIR_REG_INT_SETTING, ret); | ||
| 312 | return ret; | ||
| 313 | } | ||
| 314 | |||
| 315 | ts->touch_ind_mode = pdata->int_setting == AUO_PIXCIR_INT_TOUCH_IND; | ||
| 316 | |||
| 317 | return 0; | ||
| 318 | } | ||
| 319 | |||
| 320 | /* control the generation of interrupts on the device side */ | ||
| 321 | static int auo_pixcir_int_toggle(struct auo_pixcir_ts *ts, bool enable) | ||
| 322 | { | ||
| 323 | struct i2c_client *client = ts->client; | ||
| 324 | int ret; | ||
| 325 | |||
| 326 | ret = i2c_smbus_read_byte_data(client, AUO_PIXCIR_REG_INT_SETTING); | ||
| 327 | if (ret < 0) { | ||
| 328 | dev_err(&client->dev, "unable to read reg %Xh, %d\n", | ||
| 329 | AUO_PIXCIR_REG_INT_SETTING, ret); | ||
| 330 | return ret; | ||
| 331 | } | ||
| 332 | |||
| 333 | if (enable) | ||
| 334 | ret |= AUO_PIXCIR_INT_ENABLE; | ||
| 335 | else | ||
| 336 | ret &= ~AUO_PIXCIR_INT_ENABLE; | ||
| 337 | |||
| 338 | ret = i2c_smbus_write_byte_data(client, AUO_PIXCIR_REG_INT_SETTING, | ||
| 339 | ret); | ||
| 340 | if (ret < 0) { | ||
| 341 | dev_err(&client->dev, "unable to write reg %Xh, %d\n", | ||
| 342 | AUO_PIXCIR_REG_INT_SETTING, ret); | ||
| 343 | return ret; | ||
| 344 | } | ||
| 345 | |||
| 346 | return 0; | ||
| 347 | } | ||
| 348 | |||
| 349 | static int auo_pixcir_start(struct auo_pixcir_ts *ts) | ||
| 350 | { | ||
| 351 | struct i2c_client *client = ts->client; | ||
| 352 | int ret; | ||
| 353 | |||
| 354 | ret = auo_pixcir_power_mode(ts, AUO_PIXCIR_POWER_ACTIVE); | ||
| 355 | if (ret < 0) { | ||
| 356 | dev_err(&client->dev, "could not set power mode, %d\n", | ||
| 357 | ret); | ||
| 358 | return ret; | ||
| 359 | } | ||
| 360 | |||
| 361 | ts->stopped = false; | ||
| 362 | mb(); | ||
| 363 | enable_irq(client->irq); | ||
| 364 | |||
| 365 | ret = auo_pixcir_int_toggle(ts, 1); | ||
| 366 | if (ret < 0) { | ||
| 367 | dev_err(&client->dev, "could not enable interrupt, %d\n", | ||
| 368 | ret); | ||
| 369 | disable_irq(client->irq); | ||
| 370 | return ret; | ||
| 371 | } | ||
| 372 | |||
| 373 | return 0; | ||
| 374 | } | ||
| 375 | |||
| 376 | static int auo_pixcir_stop(struct auo_pixcir_ts *ts) | ||
| 377 | { | ||
| 378 | struct i2c_client *client = ts->client; | ||
| 379 | int ret; | ||
| 380 | |||
| 381 | ret = auo_pixcir_int_toggle(ts, 0); | ||
| 382 | if (ret < 0) { | ||
| 383 | dev_err(&client->dev, "could not disable interrupt, %d\n", | ||
| 384 | ret); | ||
| 385 | return ret; | ||
| 386 | } | ||
| 387 | |||
| 388 | /* disable receiving of interrupts */ | ||
| 389 | disable_irq(client->irq); | ||
| 390 | ts->stopped = true; | ||
| 391 | mb(); | ||
| 392 | wake_up(&ts->wait); | ||
| 393 | |||
| 394 | return auo_pixcir_power_mode(ts, AUO_PIXCIR_POWER_DEEP_SLEEP); | ||
| 395 | } | ||
| 396 | |||
| 397 | static int auo_pixcir_input_open(struct input_dev *dev) | ||
| 398 | { | ||
| 399 | struct auo_pixcir_ts *ts = input_get_drvdata(dev); | ||
| 400 | int ret; | ||
| 401 | |||
| 402 | ret = auo_pixcir_start(ts); | ||
| 403 | if (ret) | ||
| 404 | return ret; | ||
| 405 | |||
| 406 | return 0; | ||
| 407 | } | ||
| 408 | |||
| 409 | static void auo_pixcir_input_close(struct input_dev *dev) | ||
| 410 | { | ||
| 411 | struct auo_pixcir_ts *ts = input_get_drvdata(dev); | ||
| 412 | |||
| 413 | auo_pixcir_stop(ts); | ||
| 414 | |||
| 415 | return; | ||
| 416 | } | ||
| 417 | |||
| 418 | #ifdef CONFIG_PM_SLEEP | ||
| 419 | static int auo_pixcir_suspend(struct device *dev) | ||
| 420 | { | ||
| 421 | struct i2c_client *client = to_i2c_client(dev); | ||
| 422 | struct auo_pixcir_ts *ts = i2c_get_clientdata(client); | ||
| 423 | struct input_dev *input = ts->input; | ||
| 424 | int ret = 0; | ||
| 425 | |||
| 426 | mutex_lock(&input->mutex); | ||
| 427 | |||
| 428 | /* when configured as wakeup source, device should always wake system | ||
| 429 | * therefore start device if necessary | ||
| 430 | */ | ||
| 431 | if (device_may_wakeup(&client->dev)) { | ||
| 432 | /* need to start device if not open, to be wakeup source */ | ||
| 433 | if (!input->users) { | ||
| 434 | ret = auo_pixcir_start(ts); | ||
| 435 | if (ret) | ||
| 436 | goto unlock; | ||
| 437 | } | ||
| 438 | |||
| 439 | enable_irq_wake(client->irq); | ||
| 440 | ret = auo_pixcir_power_mode(ts, AUO_PIXCIR_POWER_SLEEP); | ||
| 441 | } else if (input->users) { | ||
| 442 | ret = auo_pixcir_stop(ts); | ||
| 443 | } | ||
| 444 | |||
| 445 | unlock: | ||
| 446 | mutex_unlock(&input->mutex); | ||
| 447 | |||
| 448 | return ret; | ||
| 449 | } | ||
| 450 | |||
| 451 | static int auo_pixcir_resume(struct device *dev) | ||
| 452 | { | ||
| 453 | struct i2c_client *client = to_i2c_client(dev); | ||
| 454 | struct auo_pixcir_ts *ts = i2c_get_clientdata(client); | ||
| 455 | struct input_dev *input = ts->input; | ||
| 456 | int ret = 0; | ||
| 457 | |||
| 458 | mutex_lock(&input->mutex); | ||
| 459 | |||
| 460 | if (device_may_wakeup(&client->dev)) { | ||
| 461 | disable_irq_wake(client->irq); | ||
| 462 | |||
| 463 | /* need to stop device if it was not open on suspend */ | ||
| 464 | if (!input->users) { | ||
| 465 | ret = auo_pixcir_stop(ts); | ||
| 466 | if (ret) | ||
| 467 | goto unlock; | ||
| 468 | } | ||
| 469 | |||
| 470 | /* device wakes automatically from SLEEP */ | ||
| 471 | } else if (input->users) { | ||
| 472 | ret = auo_pixcir_start(ts); | ||
| 473 | } | ||
| 474 | |||
| 475 | unlock: | ||
| 476 | mutex_unlock(&input->mutex); | ||
| 477 | |||
| 478 | return ret; | ||
| 479 | } | ||
| 480 | #endif | ||
| 481 | |||
| 482 | static SIMPLE_DEV_PM_OPS(auo_pixcir_pm_ops, auo_pixcir_suspend, | ||
| 483 | auo_pixcir_resume); | ||
| 484 | |||
| 485 | static int auo_pixcir_probe(struct i2c_client *client, | ||
| 486 | const struct i2c_device_id *id) | ||
| 487 | { | ||
| 488 | const struct auo_pixcir_ts_platdata *pdata = client->dev.platform_data; | ||
| 489 | struct auo_pixcir_ts *ts; | ||
| 490 | struct input_dev *input_dev; | ||
| 491 | int ret; | ||
| 492 | |||
| 493 | if (!pdata) | ||
| 494 | return -EINVAL; | ||
| 495 | |||
| 496 | ts = kzalloc(sizeof(struct auo_pixcir_ts), GFP_KERNEL); | ||
| 497 | if (!ts) | ||
| 498 | return -ENOMEM; | ||
| 499 | |||
| 500 | ret = gpio_request(pdata->gpio_int, "auo_pixcir_ts_int"); | ||
| 501 | if (ret) { | ||
| 502 | dev_err(&client->dev, "request of gpio %d failed, %d\n", | ||
| 503 | pdata->gpio_int, ret); | ||
| 504 | goto err_gpio_int; | ||
| 505 | } | ||
| 506 | |||
| 507 | if (pdata->init_hw) | ||
| 508 | pdata->init_hw(client); | ||
| 509 | |||
| 510 | ts->client = client; | ||
| 511 | ts->touch_ind_mode = 0; | ||
| 512 | init_waitqueue_head(&ts->wait); | ||
| 513 | |||
| 514 | snprintf(ts->phys, sizeof(ts->phys), | ||
| 515 | "%s/input0", dev_name(&client->dev)); | ||
| 516 | |||
| 517 | input_dev = input_allocate_device(); | ||
| 518 | if (!input_dev) { | ||
| 519 | dev_err(&client->dev, "could not allocate input device\n"); | ||
| 520 | goto err_input_alloc; | ||
| 521 | } | ||
| 522 | |||
| 523 | ts->input = input_dev; | ||
| 524 | |||
| 525 | input_dev->name = "AUO-Pixcir touchscreen"; | ||
| 526 | input_dev->phys = ts->phys; | ||
| 527 | input_dev->id.bustype = BUS_I2C; | ||
| 528 | input_dev->dev.parent = &client->dev; | ||
| 529 | |||
| 530 | input_dev->open = auo_pixcir_input_open; | ||
| 531 | input_dev->close = auo_pixcir_input_close; | ||
| 532 | |||
| 533 | __set_bit(EV_ABS, input_dev->evbit); | ||
| 534 | __set_bit(EV_KEY, input_dev->evbit); | ||
| 535 | |||
| 536 | __set_bit(BTN_TOUCH, input_dev->keybit); | ||
| 537 | |||
| 538 | /* For single touch */ | ||
| 539 | input_set_abs_params(input_dev, ABS_X, 0, pdata->x_max, 0, 0); | ||
| 540 | input_set_abs_params(input_dev, ABS_Y, 0, pdata->y_max, 0, 0); | ||
| 541 | |||
| 542 | /* For multi touch */ | ||
| 543 | input_set_abs_params(input_dev, ABS_MT_POSITION_X, 0, | ||
| 544 | pdata->x_max, 0, 0); | ||
| 545 | input_set_abs_params(input_dev, ABS_MT_POSITION_Y, 0, | ||
| 546 | pdata->y_max, 0, 0); | ||
| 547 | input_set_abs_params(input_dev, ABS_MT_TOUCH_MAJOR, 0, | ||
| 548 | AUO_PIXCIR_MAX_AREA, 0, 0); | ||
| 549 | input_set_abs_params(input_dev, ABS_MT_TOUCH_MINOR, 0, | ||
| 550 | AUO_PIXCIR_MAX_AREA, 0, 0); | ||
| 551 | input_set_abs_params(input_dev, ABS_MT_ORIENTATION, 0, 1, 0, 0); | ||
| 552 | |||
| 553 | ret = i2c_smbus_read_byte_data(client, AUO_PIXCIR_REG_VERSION); | ||
| 554 | if (ret < 0) | ||
| 555 | goto err_fw_vers; | ||
| 556 | dev_info(&client->dev, "firmware version 0x%X\n", ret); | ||
| 557 | |||
| 558 | ret = auo_pixcir_int_config(ts, pdata->int_setting); | ||
| 559 | if (ret) | ||
| 560 | goto err_fw_vers; | ||
| 561 | |||
| 562 | input_set_drvdata(ts->input, ts); | ||
| 563 | ts->stopped = true; | ||
| 564 | |||
| 565 | ret = request_threaded_irq(client->irq, NULL, auo_pixcir_interrupt, | ||
| 566 | IRQF_TRIGGER_RISING | IRQF_ONESHOT, | ||
| 567 | input_dev->name, ts); | ||
| 568 | if (ret) { | ||
| 569 | dev_err(&client->dev, "irq %d requested failed\n", client->irq); | ||
| 570 | goto err_fw_vers; | ||
| 571 | } | ||
| 572 | |||
| 573 | /* stop device and put it into deep sleep until it is opened */ | ||
| 574 | ret = auo_pixcir_stop(ts); | ||
| 575 | if (ret < 0) | ||
| 576 | goto err_input_register; | ||
| 577 | |||
| 578 | ret = input_register_device(input_dev); | ||
| 579 | if (ret) { | ||
| 580 | dev_err(&client->dev, "could not register input device\n"); | ||
| 581 | goto err_input_register; | ||
| 582 | } | ||
| 583 | |||
| 584 | i2c_set_clientdata(client, ts); | ||
| 585 | |||
| 586 | return 0; | ||
| 587 | |||
| 588 | err_input_register: | ||
| 589 | free_irq(client->irq, ts); | ||
| 590 | err_fw_vers: | ||
| 591 | input_free_device(input_dev); | ||
| 592 | err_input_alloc: | ||
| 593 | if (pdata->exit_hw) | ||
| 594 | pdata->exit_hw(client); | ||
| 595 | gpio_free(pdata->gpio_int); | ||
| 596 | err_gpio_int: | ||
| 597 | kfree(ts); | ||
| 598 | |||
| 599 | return ret; | ||
| 600 | } | ||
| 601 | |||
| 602 | static int auo_pixcir_remove(struct i2c_client *client) | ||
| 603 | { | ||
| 604 | struct auo_pixcir_ts *ts = i2c_get_clientdata(client); | ||
| 605 | const struct auo_pixcir_ts_platdata *pdata = client->dev.platform_data; | ||
| 606 | |||
| 607 | free_irq(client->irq, ts); | ||
| 608 | |||
| 609 | input_unregister_device(ts->input); | ||
| 610 | |||
| 611 | if (pdata->exit_hw) | ||
| 612 | pdata->exit_hw(client); | ||
| 613 | |||
| 614 | gpio_free(pdata->gpio_int); | ||
| 615 | |||
| 616 | kfree(ts); | ||
| 617 | |||
| 618 | return 0; | ||
| 619 | } | ||
| 620 | |||
| 621 | static const struct i2c_device_id auo_pixcir_idtable[] = { | ||
| 622 | { "auo_pixcir_ts", 0 }, | ||
| 623 | { } | ||
| 624 | }; | ||
| 625 | MODULE_DEVICE_TABLE(i2c, auo_pixcir_idtable); | ||
| 626 | |||
| 627 | static struct i2c_driver auo_pixcir_driver = { | ||
| 628 | .driver = { | ||
| 629 | .owner = THIS_MODULE, | ||
| 630 | .name = "auo_pixcir_ts", | ||
| 631 | .pm = &auo_pixcir_pm_ops, | ||
| 632 | }, | ||
| 633 | .probe = auo_pixcir_probe, | ||
| 634 | .remove = auo_pixcir_remove, | ||
| 635 | .id_table = auo_pixcir_idtable, | ||
| 636 | }; | ||
| 637 | |||
| 638 | module_i2c_driver(auo_pixcir_driver); | ||
| 639 | |||
| 640 | MODULE_DESCRIPTION("AUO-PIXCIR touchscreen driver"); | ||
| 641 | MODULE_LICENSE("GPL v2"); | ||
| 642 | MODULE_AUTHOR("Heiko Stuebner <heiko@sntech.de>"); | ||
diff --git a/drivers/input/touchscreen/bu21013_ts.c b/drivers/input/touchscreen/bu21013_ts.c index b9b5ddad665..1507ce108d5 100644 --- a/drivers/input/touchscreen/bu21013_ts.c +++ b/drivers/input/touchscreen/bu21013_ts.c | |||
| @@ -13,10 +13,6 @@ | |||
| 13 | #include <linux/input/bu21013.h> | 13 | #include <linux/input/bu21013.h> |
| 14 | #include <linux/slab.h> | 14 | #include <linux/slab.h> |
| 15 | #include <linux/regulator/consumer.h> | 15 | #include <linux/regulator/consumer.h> |
| 16 | #include <linux/module.h> | ||
| 17 | #include <linux/gpio.h> | ||
| 18 | #include <linux/of.h> | ||
| 19 | #include <linux/of_gpio.h> | ||
| 20 | 16 | ||
| 21 | #define PEN_DOWN_INTR 0 | 17 | #define PEN_DOWN_INTR 0 |
| 22 | #define MAX_FINGERS 2 | 18 | #define MAX_FINGERS 2 |
| @@ -151,12 +147,11 @@ | |||
| 151 | struct bu21013_ts_data { | 147 | struct bu21013_ts_data { |
| 152 | struct i2c_client *client; | 148 | struct i2c_client *client; |
| 153 | wait_queue_head_t wait; | 149 | wait_queue_head_t wait; |
| 150 | bool touch_stopped; | ||
| 154 | const struct bu21013_platform_device *chip; | 151 | const struct bu21013_platform_device *chip; |
| 155 | struct input_dev *in_dev; | 152 | struct input_dev *in_dev; |
| 156 | struct regulator *regulator; | ||
| 157 | unsigned int irq; | ||
| 158 | unsigned int intr_pin; | 153 | unsigned int intr_pin; |
| 159 | bool touch_stopped; | 154 | struct regulator *regulator; |
| 160 | }; | 155 | }; |
| 161 | 156 | ||
| 162 | /** | 157 | /** |
| @@ -266,7 +261,7 @@ static irqreturn_t bu21013_gpio_irq(int irq, void *device_data) | |||
| 266 | return IRQ_NONE; | 261 | return IRQ_NONE; |
| 267 | } | 262 | } |
| 268 | 263 | ||
| 269 | data->intr_pin = gpio_get_value(data->chip->touch_pin); | 264 | data->intr_pin = data->chip->irq_read_val(); |
| 270 | if (data->intr_pin == PEN_DOWN_INTR) | 265 | if (data->intr_pin == PEN_DOWN_INTR) |
| 271 | wait_event_timeout(data->wait, data->touch_stopped, | 266 | wait_event_timeout(data->wait, data->touch_stopped, |
| 272 | msecs_to_jiffies(2)); | 267 | msecs_to_jiffies(2)); |
| @@ -422,72 +417,10 @@ static void bu21013_free_irq(struct bu21013_ts_data *bu21013_data) | |||
| 422 | { | 417 | { |
| 423 | bu21013_data->touch_stopped = true; | 418 | bu21013_data->touch_stopped = true; |
| 424 | wake_up(&bu21013_data->wait); | 419 | wake_up(&bu21013_data->wait); |
| 425 | free_irq(bu21013_data->irq, bu21013_data); | 420 | free_irq(bu21013_data->chip->irq, bu21013_data); |
| 426 | } | 421 | } |
| 427 | 422 | ||
| 428 | /** | 423 | /** |
| 429 | * bu21013_cs_disable() - deconfigures the touch panel controller | ||
| 430 | * @bu21013_data: device structure pointer | ||
| 431 | * | ||
| 432 | * This function is used to deconfigure the chip selection | ||
| 433 | * for touch panel controller. | ||
| 434 | */ | ||
| 435 | static void bu21013_cs_disable(struct bu21013_ts_data *bu21013_data) | ||
| 436 | { | ||
| 437 | int error; | ||
| 438 | |||
| 439 | error = gpio_direction_output(bu21013_data->chip->cs_pin, 0); | ||
| 440 | if (error < 0) | ||
| 441 | dev_warn(&bu21013_data->client->dev, | ||
| 442 | "%s: gpio direction failed, error: %d\n", | ||
| 443 | __func__, error); | ||
| 444 | else | ||
| 445 | gpio_set_value(bu21013_data->chip->cs_pin, 0); | ||
| 446 | |||
| 447 | gpio_free(bu21013_data->chip->cs_pin); | ||
| 448 | } | ||
| 449 | |||
| 450 | #ifdef CONFIG_OF | ||
| 451 | static const struct bu21013_platform_device * | ||
| 452 | bu21013_parse_dt(struct device *dev) | ||
| 453 | { | ||
| 454 | struct device_node *np = dev->of_node; | ||
| 455 | struct bu21013_platform_device *pdata; | ||
| 456 | |||
| 457 | if (!np) { | ||
| 458 | dev_err(dev, "no device tree or platform data\n"); | ||
| 459 | return ERR_PTR(-EINVAL); | ||
| 460 | } | ||
| 461 | |||
| 462 | pdata = devm_kzalloc(dev, sizeof(*pdata), GFP_KERNEL); | ||
| 463 | if (!pdata) | ||
| 464 | return ERR_PTR(-ENOMEM); | ||
| 465 | |||
| 466 | pdata->y_flip = pdata->x_flip = false; | ||
| 467 | |||
| 468 | pdata->x_flip = of_property_read_bool(np, "rohm,flip-x"); | ||
| 469 | pdata->y_flip = of_property_read_bool(np, "rohm,flip-y"); | ||
| 470 | |||
| 471 | of_property_read_u32(np, "rohm,touch-max-x", &pdata->touch_x_max); | ||
| 472 | of_property_read_u32(np, "rohm,touch-max-y", &pdata->touch_y_max); | ||
| 473 | |||
| 474 | pdata->touch_pin = of_get_named_gpio(np, "touch-gpio", 0); | ||
| 475 | pdata->cs_pin = of_get_named_gpio(np, "reset-gpio", 0); | ||
| 476 | |||
| 477 | pdata->ext_clk = false; | ||
| 478 | |||
| 479 | return pdata; | ||
| 480 | } | ||
| 481 | #else | ||
| 482 | static inline const struct bu21013_platform_device * | ||
| 483 | bu21013_parse_dt(struct device *dev) | ||
| 484 | { | ||
| 485 | dev_err(dev, "no platform data available\n"); | ||
| 486 | return ERR_PTR(-EINVAL); | ||
| 487 | } | ||
| 488 | #endif | ||
| 489 | |||
| 490 | /** | ||
| 491 | * bu21013_probe() - initializes the i2c-client touchscreen driver | 424 | * bu21013_probe() - initializes the i2c-client touchscreen driver |
| 492 | * @client: i2c client structure pointer | 425 | * @client: i2c client structure pointer |
| 493 | * @id: i2c device id pointer | 426 | * @id: i2c device id pointer |
| @@ -495,13 +428,13 @@ bu21013_parse_dt(struct device *dev) | |||
| 495 | * This function used to initializes the i2c-client touchscreen | 428 | * This function used to initializes the i2c-client touchscreen |
| 496 | * driver and returns integer. | 429 | * driver and returns integer. |
| 497 | */ | 430 | */ |
| 498 | static int bu21013_probe(struct i2c_client *client, | 431 | static int __devinit bu21013_probe(struct i2c_client *client, |
| 499 | const struct i2c_device_id *id) | 432 | const struct i2c_device_id *id) |
| 500 | { | 433 | { |
| 501 | const struct bu21013_platform_device *pdata = | ||
| 502 | dev_get_platdata(&client->dev); | ||
| 503 | struct bu21013_ts_data *bu21013_data; | 434 | struct bu21013_ts_data *bu21013_data; |
| 504 | struct input_dev *in_dev; | 435 | struct input_dev *in_dev; |
| 436 | const struct bu21013_platform_device *pdata = | ||
| 437 | client->dev.platform_data; | ||
| 505 | int error; | 438 | int error; |
| 506 | 439 | ||
| 507 | if (!i2c_check_functionality(client->adapter, | 440 | if (!i2c_check_functionality(client->adapter, |
| @@ -511,13 +444,7 @@ static int bu21013_probe(struct i2c_client *client, | |||
| 511 | } | 444 | } |
| 512 | 445 | ||
| 513 | if (!pdata) { | 446 | if (!pdata) { |
| 514 | pdata = bu21013_parse_dt(&client->dev); | 447 | dev_err(&client->dev, "platform data not defined\n"); |
| 515 | if (IS_ERR(pdata)) | ||
| 516 | return PTR_ERR(pdata); | ||
| 517 | } | ||
| 518 | |||
| 519 | if (!gpio_is_valid(pdata->touch_pin)) { | ||
| 520 | dev_err(&client->dev, "invalid touch_pin supplied\n"); | ||
| 521 | return -EINVAL; | 448 | return -EINVAL; |
| 522 | } | 449 | } |
| 523 | 450 | ||
| @@ -532,9 +459,8 @@ static int bu21013_probe(struct i2c_client *client, | |||
| 532 | bu21013_data->in_dev = in_dev; | 459 | bu21013_data->in_dev = in_dev; |
| 533 | bu21013_data->chip = pdata; | 460 | bu21013_data->chip = pdata; |
| 534 | bu21013_data->client = client; | 461 | bu21013_data->client = client; |
| 535 | bu21013_data->irq = gpio_to_irq(pdata->touch_pin); | ||
| 536 | 462 | ||
| 537 | bu21013_data->regulator = regulator_get(&client->dev, "avdd"); | 463 | bu21013_data->regulator = regulator_get(&client->dev, "V-TOUCH"); |
| 538 | if (IS_ERR(bu21013_data->regulator)) { | 464 | if (IS_ERR(bu21013_data->regulator)) { |
| 539 | dev_err(&client->dev, "regulator_get failed\n"); | 465 | dev_err(&client->dev, "regulator_get failed\n"); |
| 540 | error = PTR_ERR(bu21013_data->regulator); | 466 | error = PTR_ERR(bu21013_data->regulator); |
| @@ -551,11 +477,12 @@ static int bu21013_probe(struct i2c_client *client, | |||
| 551 | init_waitqueue_head(&bu21013_data->wait); | 477 | init_waitqueue_head(&bu21013_data->wait); |
| 552 | 478 | ||
| 553 | /* configure the gpio pins */ | 479 | /* configure the gpio pins */ |
| 554 | error = gpio_request_one(pdata->cs_pin, GPIOF_OUT_INIT_HIGH, | 480 | if (pdata->cs_en) { |
| 555 | "touchp_reset"); | 481 | error = pdata->cs_en(pdata->cs_pin); |
| 556 | if (error < 0) { | 482 | if (error < 0) { |
| 557 | dev_err(&client->dev, "Unable to request gpio reset_pin\n"); | 483 | dev_err(&client->dev, "chip init failed\n"); |
| 558 | goto err_disable_regulator; | 484 | goto err_disable_regulator; |
| 485 | } | ||
| 559 | } | 486 | } |
| 560 | 487 | ||
| 561 | /* configure the touch panel controller */ | 488 | /* configure the touch panel controller */ |
| @@ -580,13 +507,11 @@ static int bu21013_probe(struct i2c_client *client, | |||
| 580 | pdata->touch_y_max, 0, 0); | 507 | pdata->touch_y_max, 0, 0); |
| 581 | input_set_drvdata(in_dev, bu21013_data); | 508 | input_set_drvdata(in_dev, bu21013_data); |
| 582 | 509 | ||
| 583 | error = request_threaded_irq(bu21013_data->irq, NULL, bu21013_gpio_irq, | 510 | error = request_threaded_irq(pdata->irq, NULL, bu21013_gpio_irq, |
| 584 | IRQF_TRIGGER_FALLING | IRQF_SHARED | | 511 | IRQF_TRIGGER_FALLING | IRQF_SHARED, |
| 585 | IRQF_ONESHOT, | ||
| 586 | DRIVER_TP, bu21013_data); | 512 | DRIVER_TP, bu21013_data); |
| 587 | if (error) { | 513 | if (error) { |
| 588 | dev_err(&client->dev, "request irq %d failed\n", | 514 | dev_err(&client->dev, "request irq %d failed\n", pdata->irq); |
| 589 | bu21013_data->irq); | ||
| 590 | goto err_cs_disable; | 515 | goto err_cs_disable; |
| 591 | } | 516 | } |
| 592 | 517 | ||
| @@ -604,7 +529,7 @@ static int bu21013_probe(struct i2c_client *client, | |||
| 604 | err_free_irq: | 529 | err_free_irq: |
| 605 | bu21013_free_irq(bu21013_data); | 530 | bu21013_free_irq(bu21013_data); |
| 606 | err_cs_disable: | 531 | err_cs_disable: |
| 607 | bu21013_cs_disable(bu21013_data); | 532 | pdata->cs_dis(pdata->cs_pin); |
| 608 | err_disable_regulator: | 533 | err_disable_regulator: |
| 609 | regulator_disable(bu21013_data->regulator); | 534 | regulator_disable(bu21013_data->regulator); |
| 610 | err_put_regulator: | 535 | err_put_regulator: |
| @@ -622,13 +547,13 @@ err_free_mem: | |||
| 622 | * This function uses to remove the i2c-client | 547 | * This function uses to remove the i2c-client |
| 623 | * touchscreen driver and returns integer. | 548 | * touchscreen driver and returns integer. |
| 624 | */ | 549 | */ |
| 625 | static int bu21013_remove(struct i2c_client *client) | 550 | static int __devexit bu21013_remove(struct i2c_client *client) |
| 626 | { | 551 | { |
| 627 | struct bu21013_ts_data *bu21013_data = i2c_get_clientdata(client); | 552 | struct bu21013_ts_data *bu21013_data = i2c_get_clientdata(client); |
| 628 | 553 | ||
| 629 | bu21013_free_irq(bu21013_data); | 554 | bu21013_free_irq(bu21013_data); |
| 630 | 555 | ||
| 631 | bu21013_cs_disable(bu21013_data); | 556 | bu21013_data->chip->cs_dis(bu21013_data->chip->cs_pin); |
| 632 | 557 | ||
| 633 | input_unregister_device(bu21013_data->in_dev); | 558 | input_unregister_device(bu21013_data->in_dev); |
| 634 | 559 | ||
| @@ -657,9 +582,9 @@ static int bu21013_suspend(struct device *dev) | |||
| 657 | 582 | ||
| 658 | bu21013_data->touch_stopped = true; | 583 | bu21013_data->touch_stopped = true; |
| 659 | if (device_may_wakeup(&client->dev)) | 584 | if (device_may_wakeup(&client->dev)) |
| 660 | enable_irq_wake(bu21013_data->irq); | 585 | enable_irq_wake(bu21013_data->chip->irq); |
| 661 | else | 586 | else |
| 662 | disable_irq(bu21013_data->irq); | 587 | disable_irq(bu21013_data->chip->irq); |
| 663 | 588 | ||
| 664 | regulator_disable(bu21013_data->regulator); | 589 | regulator_disable(bu21013_data->regulator); |
| 665 | 590 | ||
| @@ -694,9 +619,9 @@ static int bu21013_resume(struct device *dev) | |||
| 694 | bu21013_data->touch_stopped = false; | 619 | bu21013_data->touch_stopped = false; |
| 695 | 620 | ||
| 696 | if (device_may_wakeup(&client->dev)) | 621 | if (device_may_wakeup(&client->dev)) |
| 697 | disable_irq_wake(bu21013_data->irq); | 622 | disable_irq_wake(bu21013_data->chip->irq); |
| 698 | else | 623 | else |
| 699 | enable_irq(bu21013_data->irq); | 624 | enable_irq(bu21013_data->chip->irq); |
| 700 | 625 | ||
| 701 | return 0; | 626 | return 0; |
| 702 | } | 627 | } |
| @@ -722,11 +647,34 @@ static struct i2c_driver bu21013_driver = { | |||
| 722 | #endif | 647 | #endif |
| 723 | }, | 648 | }, |
| 724 | .probe = bu21013_probe, | 649 | .probe = bu21013_probe, |
| 725 | .remove = bu21013_remove, | 650 | .remove = __devexit_p(bu21013_remove), |
| 726 | .id_table = bu21013_id, | 651 | .id_table = bu21013_id, |
| 727 | }; | 652 | }; |
| 728 | 653 | ||
| 729 | module_i2c_driver(bu21013_driver); | 654 | /** |
| 655 | * bu21013_init() - initializes the bu21013 touchscreen driver | ||
| 656 | * | ||
| 657 | * This function used to initializes the bu21013 | ||
| 658 | * touchscreen driver and returns integer. | ||
| 659 | */ | ||
| 660 | static int __init bu21013_init(void) | ||
| 661 | { | ||
| 662 | return i2c_add_driver(&bu21013_driver); | ||
| 663 | } | ||
| 664 | |||
| 665 | /** | ||
| 666 | * bu21013_exit() - de-initializes the bu21013 touchscreen driver | ||
| 667 | * | ||
| 668 | * This function uses to de-initializes the bu21013 | ||
| 669 | * touchscreen driver and returns none. | ||
| 670 | */ | ||
| 671 | static void __exit bu21013_exit(void) | ||
| 672 | { | ||
| 673 | i2c_del_driver(&bu21013_driver); | ||
| 674 | } | ||
| 675 | |||
| 676 | module_init(bu21013_init); | ||
| 677 | module_exit(bu21013_exit); | ||
| 730 | 678 | ||
| 731 | MODULE_LICENSE("GPL v2"); | 679 | MODULE_LICENSE("GPL v2"); |
| 732 | MODULE_AUTHOR("Naveen Kumar G <naveen.gaddipati@stericsson.com>"); | 680 | MODULE_AUTHOR("Naveen Kumar G <naveen.gaddipati@stericsson.com>"); |
diff --git a/drivers/input/touchscreen/cy8ctmg110_ts.c b/drivers/input/touchscreen/cy8ctmg110_ts.c index 96e0eedcc7e..d8815c5d54a 100644 --- a/drivers/input/touchscreen/cy8ctmg110_ts.c +++ b/drivers/input/touchscreen/cy8ctmg110_ts.c | |||
| @@ -99,18 +99,9 @@ static int cy8ctmg110_read_regs(struct cy8ctmg110 *tsc, | |||
| 99 | int ret; | 99 | int ret; |
| 100 | struct i2c_msg msg[2] = { | 100 | struct i2c_msg msg[2] = { |
| 101 | /* first write slave position to i2c devices */ | 101 | /* first write slave position to i2c devices */ |
| 102 | { | 102 | { client->addr, 0, 1, &cmd }, |
| 103 | .addr = client->addr, | ||
| 104 | .len = 1, | ||
| 105 | .buf = &cmd | ||
| 106 | }, | ||
| 107 | /* Second read data from position */ | 103 | /* Second read data from position */ |
| 108 | { | 104 | { client->addr, I2C_M_RD, len, data } |
| 109 | .addr = client->addr, | ||
| 110 | .flags = I2C_M_RD, | ||
| 111 | .len = len, | ||
| 112 | .buf = data | ||
| 113 | } | ||
| 114 | }; | 105 | }; |
| 115 | 106 | ||
| 116 | ret = i2c_transfer(client->adapter, msg, 2); | 107 | ret = i2c_transfer(client->adapter, msg, 2); |
| @@ -175,7 +166,7 @@ static irqreturn_t cy8ctmg110_irq_thread(int irq, void *dev_id) | |||
| 175 | return IRQ_HANDLED; | 166 | return IRQ_HANDLED; |
| 176 | } | 167 | } |
| 177 | 168 | ||
| 178 | static int cy8ctmg110_probe(struct i2c_client *client, | 169 | static int __devinit cy8ctmg110_probe(struct i2c_client *client, |
| 179 | const struct i2c_device_id *id) | 170 | const struct i2c_device_id *id) |
| 180 | { | 171 | { |
| 181 | const struct cy8ctmg110_pdata *pdata = client->dev.platform_data; | 172 | const struct cy8ctmg110_pdata *pdata = client->dev.platform_data; |
| @@ -260,8 +251,7 @@ static int cy8ctmg110_probe(struct i2c_client *client, | |||
| 260 | } | 251 | } |
| 261 | 252 | ||
| 262 | err = request_threaded_irq(client->irq, NULL, cy8ctmg110_irq_thread, | 253 | err = request_threaded_irq(client->irq, NULL, cy8ctmg110_irq_thread, |
| 263 | IRQF_TRIGGER_RISING | IRQF_ONESHOT, | 254 | IRQF_TRIGGER_RISING, "touch_reset_key", ts); |
| 264 | "touch_reset_key", ts); | ||
| 265 | if (err < 0) { | 255 | if (err < 0) { |
| 266 | dev_err(&client->dev, | 256 | dev_err(&client->dev, |
| 267 | "irq %d busy? error %d\n", client->irq, err); | 257 | "irq %d busy? error %d\n", client->irq, err); |
| @@ -323,7 +313,7 @@ static int cy8ctmg110_resume(struct device *dev) | |||
| 323 | static SIMPLE_DEV_PM_OPS(cy8ctmg110_pm, cy8ctmg110_suspend, cy8ctmg110_resume); | 313 | static SIMPLE_DEV_PM_OPS(cy8ctmg110_pm, cy8ctmg110_suspend, cy8ctmg110_resume); |
| 324 | #endif | 314 | #endif |
| 325 | 315 | ||
| 326 | static int cy8ctmg110_remove(struct i2c_client *client) | 316 | static int __devexit cy8ctmg110_remove(struct i2c_client *client) |
| 327 | { | 317 | { |
| 328 | struct cy8ctmg110 *ts = i2c_get_clientdata(client); | 318 | struct cy8ctmg110 *ts = i2c_get_clientdata(client); |
| 329 | 319 | ||
| @@ -357,10 +347,21 @@ static struct i2c_driver cy8ctmg110_driver = { | |||
| 357 | }, | 347 | }, |
| 358 | .id_table = cy8ctmg110_idtable, | 348 | .id_table = cy8ctmg110_idtable, |
| 359 | .probe = cy8ctmg110_probe, | 349 | .probe = cy8ctmg110_probe, |
| 360 | .remove = cy8ctmg110_remove, | 350 | .remove = __devexit_p(cy8ctmg110_remove), |
| 361 | }; | 351 | }; |
| 362 | 352 | ||
| 363 | module_i2c_driver(cy8ctmg110_driver); | 353 | static int __init cy8ctmg110_init(void) |
| 354 | { | ||
| 355 | return i2c_add_driver(&cy8ctmg110_driver); | ||
| 356 | } | ||
| 357 | |||
| 358 | static void __exit cy8ctmg110_exit(void) | ||
| 359 | { | ||
| 360 | i2c_del_driver(&cy8ctmg110_driver); | ||
| 361 | } | ||
| 362 | |||
| 363 | module_init(cy8ctmg110_init); | ||
| 364 | module_exit(cy8ctmg110_exit); | ||
| 364 | 365 | ||
| 365 | MODULE_AUTHOR("Samuli Konttila <samuli.konttila@aavamobile.com>"); | 366 | MODULE_AUTHOR("Samuli Konttila <samuli.konttila@aavamobile.com>"); |
| 366 | MODULE_DESCRIPTION("cy8ctmg110 TouchScreen Driver"); | 367 | MODULE_DESCRIPTION("cy8ctmg110 TouchScreen Driver"); |
diff --git a/drivers/input/touchscreen/cyttsp_core.c b/drivers/input/touchscreen/cyttsp_core.c deleted file mode 100644 index 8e60437ac85..00000000000 --- a/drivers/input/touchscreen/cyttsp_core.c +++ /dev/null | |||
| @@ -1,625 +0,0 @@ | |||
| 1 | /* | ||
| 2 | * Core Source for: | ||
| 3 | * Cypress TrueTouch(TM) Standard Product (TTSP) touchscreen drivers. | ||
| 4 | * For use with Cypress Txx3xx parts. | ||
| 5 | * Supported parts include: | ||
| 6 | * CY8CTST341 | ||
| 7 | * CY8CTMA340 | ||
| 8 | * | ||
| 9 | * Copyright (C) 2009, 2010, 2011 Cypress Semiconductor, Inc. | ||
| 10 | * Copyright (C) 2012 Javier Martinez Canillas <javier@dowhile0.org> | ||
| 11 | * | ||
| 12 | * This program is free software; you can redistribute it and/or | ||
| 13 | * modify it under the terms of the GNU General Public License | ||
| 14 | * version 2, and only version 2, as published by the | ||
| 15 | * Free Software Foundation. | ||
| 16 | * | ||
| 17 | * This program is distributed in the hope that it will be useful, | ||
| 18 | * but WITHOUT ANY WARRANTY; without even the implied warranty of | ||
| 19 | * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the | ||
| 20 | * GNU General Public License for more details. | ||
| 21 | * | ||
| 22 | * You should have received a copy of the GNU General Public License along | ||
| 23 | * with this program; if not, write to the Free Software Foundation, Inc., | ||
| 24 | * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. | ||
| 25 | * | ||
| 26 | * Contact Cypress Semiconductor at www.cypress.com <kev@cypress.com> | ||
| 27 | * | ||
| 28 | */ | ||
| 29 | |||
| 30 | #include <linux/delay.h> | ||
| 31 | #include <linux/input.h> | ||
| 32 | #include <linux/input/mt.h> | ||
| 33 | #include <linux/gpio.h> | ||
| 34 | #include <linux/interrupt.h> | ||
| 35 | #include <linux/slab.h> | ||
| 36 | |||
| 37 | #include "cyttsp_core.h" | ||
| 38 | |||
| 39 | /* Bootloader number of command keys */ | ||
| 40 | #define CY_NUM_BL_KEYS 8 | ||
| 41 | |||
| 42 | /* helpers */ | ||
| 43 | #define GET_NUM_TOUCHES(x) ((x) & 0x0F) | ||
| 44 | #define IS_LARGE_AREA(x) (((x) & 0x10) >> 4) | ||
| 45 | #define IS_BAD_PKT(x) ((x) & 0x20) | ||
| 46 | #define IS_VALID_APP(x) ((x) & 0x01) | ||
| 47 | #define IS_OPERATIONAL_ERR(x) ((x) & 0x3F) | ||
| 48 | #define GET_HSTMODE(reg) (((reg) & 0x70) >> 4) | ||
| 49 | #define GET_BOOTLOADERMODE(reg) (((reg) & 0x10) >> 4) | ||
| 50 | |||
| 51 | #define CY_REG_BASE 0x00 | ||
| 52 | #define CY_REG_ACT_DIST 0x1E | ||
| 53 | #define CY_REG_ACT_INTRVL 0x1D | ||
| 54 | #define CY_REG_TCH_TMOUT (CY_REG_ACT_INTRVL + 1) | ||
| 55 | #define CY_REG_LP_INTRVL (CY_REG_TCH_TMOUT + 1) | ||
| 56 | #define CY_MAXZ 255 | ||
| 57 | #define CY_DELAY_DFLT 20 /* ms */ | ||
| 58 | #define CY_DELAY_MAX 500 | ||
| 59 | #define CY_ACT_DIST_DFLT 0xF8 | ||
| 60 | #define CY_HNDSHK_BIT 0x80 | ||
| 61 | /* device mode bits */ | ||
| 62 | #define CY_OPERATE_MODE 0x00 | ||
| 63 | #define CY_SYSINFO_MODE 0x10 | ||
| 64 | /* power mode select bits */ | ||
| 65 | #define CY_SOFT_RESET_MODE 0x01 /* return to Bootloader mode */ | ||
| 66 | #define CY_DEEP_SLEEP_MODE 0x02 | ||
| 67 | #define CY_LOW_POWER_MODE 0x04 | ||
| 68 | |||
| 69 | /* Slots management */ | ||
| 70 | #define CY_MAX_FINGER 4 | ||
| 71 | #define CY_MAX_ID 16 | ||
| 72 | |||
| 73 | static const u8 bl_command[] = { | ||
| 74 | 0x00, /* file offset */ | ||
| 75 | 0xFF, /* command */ | ||
| 76 | 0xA5, /* exit bootloader command */ | ||
| 77 | 0, 1, 2, 3, 4, 5, 6, 7 /* default keys */ | ||
| 78 | }; | ||
| 79 | |||
| 80 | static int ttsp_read_block_data(struct cyttsp *ts, u8 command, | ||
| 81 | u8 length, void *buf) | ||
| 82 | { | ||
| 83 | int error; | ||
| 84 | int tries; | ||
| 85 | |||
| 86 | for (tries = 0; tries < CY_NUM_RETRY; tries++) { | ||
| 87 | error = ts->bus_ops->read(ts, command, length, buf); | ||
| 88 | if (!error) | ||
| 89 | return 0; | ||
| 90 | |||
| 91 | msleep(CY_DELAY_DFLT); | ||
| 92 | } | ||
| 93 | |||
| 94 | return -EIO; | ||
| 95 | } | ||
| 96 | |||
| 97 | static int ttsp_write_block_data(struct cyttsp *ts, u8 command, | ||
| 98 | u8 length, void *buf) | ||
| 99 | { | ||
| 100 | int error; | ||
| 101 | int tries; | ||
| 102 | |||
| 103 | for (tries = 0; tries < CY_NUM_RETRY; tries++) { | ||
| 104 | error = ts->bus_ops->write(ts, command, length, buf); | ||
| 105 | if (!error) | ||
| 106 | return 0; | ||
| 107 | |||
| 108 | msleep(CY_DELAY_DFLT); | ||
| 109 | } | ||
| 110 | |||
| 111 | return -EIO; | ||
| 112 | } | ||
| 113 | |||
| 114 | static int ttsp_send_command(struct cyttsp *ts, u8 cmd) | ||
| 115 | { | ||
| 116 | return ttsp_write_block_data(ts, CY_REG_BASE, sizeof(cmd), &cmd); | ||
| 117 | } | ||
| 118 | |||
| 119 | static int cyttsp_load_bl_regs(struct cyttsp *ts) | ||
| 120 | { | ||
| 121 | memset(&ts->bl_data, 0, sizeof(ts->bl_data)); | ||
| 122 | ts->bl_data.bl_status = 0x10; | ||
| 123 | |||
| 124 | return ttsp_read_block_data(ts, CY_REG_BASE, | ||
| 125 | sizeof(ts->bl_data), &ts->bl_data); | ||
| 126 | } | ||
| 127 | |||
| 128 | static int cyttsp_exit_bl_mode(struct cyttsp *ts) | ||
| 129 | { | ||
| 130 | int error; | ||
| 131 | u8 bl_cmd[sizeof(bl_command)]; | ||
| 132 | |||
| 133 | memcpy(bl_cmd, bl_command, sizeof(bl_command)); | ||
| 134 | if (ts->pdata->bl_keys) | ||
| 135 | memcpy(&bl_cmd[sizeof(bl_command) - CY_NUM_BL_KEYS], | ||
| 136 | ts->pdata->bl_keys, sizeof(bl_command)); | ||
| 137 | |||
| 138 | error = ttsp_write_block_data(ts, CY_REG_BASE, | ||
| 139 | sizeof(bl_cmd), bl_cmd); | ||
| 140 | if (error) | ||
| 141 | return error; | ||
| 142 | |||
| 143 | /* wait for TTSP Device to complete the operation */ | ||
| 144 | msleep(CY_DELAY_DFLT); | ||
| 145 | |||
| 146 | error = cyttsp_load_bl_regs(ts); | ||
| 147 | if (error) | ||
| 148 | return error; | ||
| 149 | |||
| 150 | if (GET_BOOTLOADERMODE(ts->bl_data.bl_status)) | ||
| 151 | return -EIO; | ||
| 152 | |||
| 153 | return 0; | ||
| 154 | } | ||
| 155 | |||
| 156 | static int cyttsp_set_operational_mode(struct cyttsp *ts) | ||
| 157 | { | ||
| 158 | int error; | ||
| 159 | |||
| 160 | error = ttsp_send_command(ts, CY_OPERATE_MODE); | ||
| 161 | if (error) | ||
| 162 | return error; | ||
| 163 | |||
| 164 | /* wait for TTSP Device to complete switch to Operational mode */ | ||
| 165 | error = ttsp_read_block_data(ts, CY_REG_BASE, | ||
| 166 | sizeof(ts->xy_data), &ts->xy_data); | ||
| 167 | if (error) | ||
| 168 | return error; | ||
| 169 | |||
| 170 | return ts->xy_data.act_dist == CY_ACT_DIST_DFLT ? -EIO : 0; | ||
| 171 | } | ||
| 172 | |||
| 173 | static int cyttsp_set_sysinfo_mode(struct cyttsp *ts) | ||
| 174 | { | ||
| 175 | int error; | ||
| 176 | |||
| 177 | memset(&ts->sysinfo_data, 0, sizeof(ts->sysinfo_data)); | ||
| 178 | |||
| 179 | /* switch to sysinfo mode */ | ||
| 180 | error = ttsp_send_command(ts, CY_SYSINFO_MODE); | ||
| 181 | if (error) | ||
| 182 | return error; | ||
| 183 | |||
| 184 | /* read sysinfo registers */ | ||
| 185 | msleep(CY_DELAY_DFLT); | ||
| 186 | error = ttsp_read_block_data(ts, CY_REG_BASE, sizeof(ts->sysinfo_data), | ||
| 187 | &ts->sysinfo_data); | ||
| 188 | if (error) | ||
| 189 | return error; | ||
| 190 | |||
| 191 | if (!ts->sysinfo_data.tts_verh && !ts->sysinfo_data.tts_verl) | ||
| 192 | return -EIO; | ||
| 193 | |||
| 194 | return 0; | ||
| 195 | } | ||
| 196 | |||
| 197 | static int cyttsp_set_sysinfo_regs(struct cyttsp *ts) | ||
| 198 | { | ||
| 199 | int retval = 0; | ||
| 200 | |||
| 201 | if (ts->pdata->act_intrvl != CY_ACT_INTRVL_DFLT || | ||
| 202 | ts->pdata->tch_tmout != CY_TCH_TMOUT_DFLT || | ||
| 203 | ts->pdata->lp_intrvl != CY_LP_INTRVL_DFLT) { | ||
| 204 | |||
| 205 | u8 intrvl_ray[] = { | ||
| 206 | ts->pdata->act_intrvl, | ||
| 207 | ts->pdata->tch_tmout, | ||
| 208 | ts->pdata->lp_intrvl | ||
| 209 | }; | ||
| 210 | |||
| 211 | /* set intrvl registers */ | ||
| 212 | retval = ttsp_write_block_data(ts, CY_REG_ACT_INTRVL, | ||
| 213 | sizeof(intrvl_ray), intrvl_ray); | ||
| 214 | msleep(CY_DELAY_DFLT); | ||
| 215 | } | ||
| 216 | |||
| 217 | return retval; | ||
| 218 | } | ||
| 219 | |||
| 220 | static int cyttsp_soft_reset(struct cyttsp *ts) | ||
| 221 | { | ||
| 222 | unsigned long timeout; | ||
| 223 | int retval; | ||
| 224 | |||
| 225 | /* wait for interrupt to set ready completion */ | ||
| 226 | INIT_COMPLETION(ts->bl_ready); | ||
| 227 | ts->state = CY_BL_STATE; | ||
| 228 | |||
| 229 | enable_irq(ts->irq); | ||
| 230 | |||
| 231 | retval = ttsp_send_command(ts, CY_SOFT_RESET_MODE); | ||
| 232 | if (retval) | ||
| 233 | goto out; | ||
| 234 | |||
| 235 | timeout = wait_for_completion_timeout(&ts->bl_ready, | ||
| 236 | msecs_to_jiffies(CY_DELAY_DFLT * CY_DELAY_MAX)); | ||
| 237 | retval = timeout ? 0 : -EIO; | ||
| 238 | |||
| 239 | out: | ||
| 240 | ts->state = CY_IDLE_STATE; | ||
| 241 | disable_irq(ts->irq); | ||
| 242 | return retval; | ||
| 243 | } | ||
| 244 | |||
| 245 | static int cyttsp_act_dist_setup(struct cyttsp *ts) | ||
| 246 | { | ||
| 247 | u8 act_dist_setup = ts->pdata->act_dist; | ||
| 248 | |||
| 249 | /* Init gesture; active distance setup */ | ||
| 250 | return ttsp_write_block_data(ts, CY_REG_ACT_DIST, | ||
| 251 | sizeof(act_dist_setup), &act_dist_setup); | ||
| 252 | } | ||
| 253 | |||
| 254 | static void cyttsp_extract_track_ids(struct cyttsp_xydata *xy_data, int *ids) | ||
| 255 | { | ||
| 256 | ids[0] = xy_data->touch12_id >> 4; | ||
| 257 | ids[1] = xy_data->touch12_id & 0xF; | ||
| 258 | ids[2] = xy_data->touch34_id >> 4; | ||
| 259 | ids[3] = xy_data->touch34_id & 0xF; | ||
| 260 | } | ||
| 261 | |||
| 262 | static const struct cyttsp_tch *cyttsp_get_tch(struct cyttsp_xydata *xy_data, | ||
| 263 | int idx) | ||
| 264 | { | ||
| 265 | switch (idx) { | ||
| 266 | case 0: | ||
| 267 | return &xy_data->tch1; | ||
| 268 | case 1: | ||
| 269 | return &xy_data->tch2; | ||
| 270 | case 2: | ||
| 271 | return &xy_data->tch3; | ||
| 272 | case 3: | ||
| 273 | return &xy_data->tch4; | ||
| 274 | default: | ||
| 275 | return NULL; | ||
| 276 | } | ||
| 277 | } | ||
| 278 | |||
| 279 | static void cyttsp_report_tchdata(struct cyttsp *ts) | ||
| 280 | { | ||
| 281 | struct cyttsp_xydata *xy_data = &ts->xy_data; | ||
| 282 | struct input_dev *input = ts->input; | ||
| 283 | int num_tch = GET_NUM_TOUCHES(xy_data->tt_stat); | ||
| 284 | const struct cyttsp_tch *tch; | ||
| 285 | int ids[CY_MAX_ID]; | ||
| 286 | int i; | ||
| 287 | DECLARE_BITMAP(used, CY_MAX_ID); | ||
| 288 | |||
| 289 | if (IS_LARGE_AREA(xy_data->tt_stat) == 1) { | ||
| 290 | /* terminate all active tracks */ | ||
| 291 | num_tch = 0; | ||
| 292 | dev_dbg(ts->dev, "%s: Large area detected\n", __func__); | ||
| 293 | } else if (num_tch > CY_MAX_FINGER) { | ||
| 294 | /* terminate all active tracks */ | ||
| 295 | num_tch = 0; | ||
| 296 | dev_dbg(ts->dev, "%s: Num touch error detected\n", __func__); | ||
| 297 | } else if (IS_BAD_PKT(xy_data->tt_mode)) { | ||
| 298 | /* terminate all active tracks */ | ||
| 299 | num_tch = 0; | ||
| 300 | dev_dbg(ts->dev, "%s: Invalid buffer detected\n", __func__); | ||
| 301 | } | ||
| 302 | |||
| 303 | cyttsp_extract_track_ids(xy_data, ids); | ||
| 304 | |||
| 305 | bitmap_zero(used, CY_MAX_ID); | ||
| 306 | |||
| 307 | for (i = 0; i < num_tch; i++) { | ||
| 308 | tch = cyttsp_get_tch(xy_data, i); | ||
| 309 | |||
| 310 | input_mt_slot(input, ids[i]); | ||
| 311 | input_mt_report_slot_state(input, MT_TOOL_FINGER, true); | ||
| 312 | input_report_abs(input, ABS_MT_POSITION_X, be16_to_cpu(tch->x)); | ||
| 313 | input_report_abs(input, ABS_MT_POSITION_Y, be16_to_cpu(tch->y)); | ||
| 314 | input_report_abs(input, ABS_MT_TOUCH_MAJOR, tch->z); | ||
| 315 | |||
| 316 | __set_bit(ids[i], used); | ||
| 317 | } | ||
| 318 | |||
| 319 | for (i = 0; i < CY_MAX_ID; i++) { | ||
| 320 | if (test_bit(i, used)) | ||
| 321 | continue; | ||
| 322 | |||
| 323 | input_mt_slot(input, i); | ||
| 324 | input_mt_report_slot_state(input, MT_TOOL_FINGER, false); | ||
| 325 | } | ||
| 326 | |||
| 327 | input_sync(input); | ||
| 328 | } | ||
| 329 | |||
| 330 | static irqreturn_t cyttsp_irq(int irq, void *handle) | ||
| 331 | { | ||
| 332 | struct cyttsp *ts = handle; | ||
| 333 | int error; | ||
| 334 | |||
| 335 | if (unlikely(ts->state == CY_BL_STATE)) { | ||
| 336 | complete(&ts->bl_ready); | ||
| 337 | goto out; | ||
| 338 | } | ||
| 339 | |||
| 340 | /* Get touch data from CYTTSP device */ | ||
| 341 | error = ttsp_read_block_data(ts, CY_REG_BASE, | ||
| 342 | sizeof(struct cyttsp_xydata), &ts->xy_data); | ||
| 343 | if (error) | ||
| 344 | goto out; | ||
| 345 | |||
| 346 | /* provide flow control handshake */ | ||
| 347 | if (ts->pdata->use_hndshk) { | ||
| 348 | error = ttsp_send_command(ts, | ||
| 349 | ts->xy_data.hst_mode ^ CY_HNDSHK_BIT); | ||
| 350 | if (error) | ||
| 351 | goto out; | ||
| 352 | } | ||
| 353 | |||
| 354 | if (unlikely(ts->state == CY_IDLE_STATE)) | ||
| 355 | goto out; | ||
| 356 | |||
| 357 | if (GET_BOOTLOADERMODE(ts->xy_data.tt_mode)) { | ||
| 358 | /* | ||
| 359 | * TTSP device has reset back to bootloader mode. | ||
| 360 | * Restore to operational mode. | ||
| 361 | */ | ||
| 362 | error = cyttsp_exit_bl_mode(ts); | ||
| 363 | if (error) { | ||
| 364 | dev_err(ts->dev, | ||
| 365 | "Could not return to operational mode, err: %d\n", | ||
| 366 | error); | ||
| 367 | ts->state = CY_IDLE_STATE; | ||
| 368 | } | ||
| 369 | } else { | ||
| 370 | cyttsp_report_tchdata(ts); | ||
| 371 | } | ||
| 372 | |||
| 373 | out: | ||
| 374 | return IRQ_HANDLED; | ||
| 375 | } | ||
| 376 | |||
| 377 | static int cyttsp_power_on(struct cyttsp *ts) | ||
| 378 | { | ||
| 379 | int error; | ||
| 380 | |||
| 381 | error = cyttsp_soft_reset(ts); | ||
| 382 | if (error) | ||
| 383 | return error; | ||
| 384 | |||
| 385 | error = cyttsp_load_bl_regs(ts); | ||
| 386 | if (error) | ||
| 387 | return error; | ||
| 388 | |||
| 389 | if (GET_BOOTLOADERMODE(ts->bl_data.bl_status) && | ||
| 390 | IS_VALID_APP(ts->bl_data.bl_status)) { | ||
| 391 | error = cyttsp_exit_bl_mode(ts); | ||
| 392 | if (error) | ||
| 393 | return error; | ||
| 394 | } | ||
| 395 | |||
| 396 | if (GET_HSTMODE(ts->bl_data.bl_file) != CY_OPERATE_MODE || | ||
| 397 | IS_OPERATIONAL_ERR(ts->bl_data.bl_status)) { | ||
| 398 | return -ENODEV; | ||
| 399 | } | ||
| 400 | |||
| 401 | error = cyttsp_set_sysinfo_mode(ts); | ||
| 402 | if (error) | ||
| 403 | return error; | ||
| 404 | |||
| 405 | error = cyttsp_set_sysinfo_regs(ts); | ||
| 406 | if (error) | ||
| 407 | return error; | ||
| 408 | |||
| 409 | error = cyttsp_set_operational_mode(ts); | ||
| 410 | if (error) | ||
| 411 | return error; | ||
| 412 | |||
| 413 | /* init active distance */ | ||
| 414 | error = cyttsp_act_dist_setup(ts); | ||
| 415 | if (error) | ||
| 416 | return error; | ||
| 417 | |||
| 418 | ts->state = CY_ACTIVE_STATE; | ||
| 419 | |||
| 420 | return 0; | ||
| 421 | } | ||
| 422 | |||
| 423 | static int cyttsp_enable(struct cyttsp *ts) | ||
| 424 | { | ||
| 425 | int error; | ||
| 426 | |||
| 427 | /* | ||
| 428 | * The device firmware can wake on an I2C or SPI memory slave | ||
| 429 | * address match. So just reading a register is sufficient to | ||
| 430 | * wake up the device. The first read attempt will fail but it | ||
| 431 | * will wake it up making the second read attempt successful. | ||
| 432 | */ | ||
| 433 | error = ttsp_read_block_data(ts, CY_REG_BASE, | ||
| 434 | sizeof(ts->xy_data), &ts->xy_data); | ||
| 435 | if (error) | ||
| 436 | return error; | ||
| 437 | |||
| 438 | if (GET_HSTMODE(ts->xy_data.hst_mode)) | ||
| 439 | return -EIO; | ||
| 440 | |||
| 441 | enable_irq(ts->irq); | ||
| 442 | |||
| 443 | return 0; | ||
| 444 | } | ||
| 445 | |||
| 446 | static int cyttsp_disable(struct cyttsp *ts) | ||
| 447 | { | ||
| 448 | int error; | ||
| 449 | |||
| 450 | error = ttsp_send_command(ts, CY_LOW_POWER_MODE); | ||
| 451 | if (error) | ||
| 452 | return error; | ||
| 453 | |||
| 454 | disable_irq(ts->irq); | ||
| 455 | |||
| 456 | return 0; | ||
| 457 | } | ||
| 458 | |||
| 459 | #ifdef CONFIG_PM_SLEEP | ||
| 460 | static int cyttsp_suspend(struct device *dev) | ||
| 461 | { | ||
| 462 | struct cyttsp *ts = dev_get_drvdata(dev); | ||
| 463 | int retval = 0; | ||
| 464 | |||
| 465 | mutex_lock(&ts->input->mutex); | ||
| 466 | |||
| 467 | if (ts->input->users) { | ||
| 468 | retval = cyttsp_disable(ts); | ||
| 469 | if (retval == 0) | ||
| 470 | ts->suspended = true; | ||
| 471 | } | ||
| 472 | |||
| 473 | mutex_unlock(&ts->input->mutex); | ||
| 474 | |||
| 475 | return retval; | ||
| 476 | } | ||
| 477 | |||
| 478 | static int cyttsp_resume(struct device *dev) | ||
| 479 | { | ||
| 480 | struct cyttsp *ts = dev_get_drvdata(dev); | ||
| 481 | |||
| 482 | mutex_lock(&ts->input->mutex); | ||
| 483 | |||
| 484 | if (ts->input->users) | ||
| 485 | cyttsp_enable(ts); | ||
| 486 | |||
| 487 | ts->suspended = false; | ||
| 488 | |||
| 489 | mutex_unlock(&ts->input->mutex); | ||
| 490 | |||
| 491 | return 0; | ||
| 492 | } | ||
| 493 | |||
| 494 | #endif | ||
| 495 | |||
| 496 | SIMPLE_DEV_PM_OPS(cyttsp_pm_ops, cyttsp_suspend, cyttsp_resume); | ||
| 497 | EXPORT_SYMBOL_GPL(cyttsp_pm_ops); | ||
| 498 | |||
| 499 | static int cyttsp_open(struct input_dev *dev) | ||
| 500 | { | ||
| 501 | struct cyttsp *ts = input_get_drvdata(dev); | ||
| 502 | int retval = 0; | ||
| 503 | |||
| 504 | if (!ts->suspended) | ||
| 505 | retval = cyttsp_enable(ts); | ||
| 506 | |||
| 507 | return retval; | ||
| 508 | } | ||
| 509 | |||
| 510 | static void cyttsp_close(struct input_dev *dev) | ||
| 511 | { | ||
| 512 | struct cyttsp *ts = input_get_drvdata(dev); | ||
| 513 | |||
| 514 | if (!ts->suspended) | ||
| 515 | cyttsp_disable(ts); | ||
| 516 | } | ||
| 517 | |||
| 518 | struct cyttsp *cyttsp_probe(const struct cyttsp_bus_ops *bus_ops, | ||
| 519 | struct device *dev, int irq, size_t xfer_buf_size) | ||
| 520 | { | ||
| 521 | const struct cyttsp_platform_data *pdata = dev->platform_data; | ||
| 522 | struct cyttsp *ts; | ||
| 523 | struct input_dev *input_dev; | ||
| 524 | int error; | ||
| 525 | |||
| 526 | if (!pdata || !pdata->name || irq <= 0) { | ||
| 527 | error = -EINVAL; | ||
| 528 | goto err_out; | ||
| 529 | } | ||
| 530 | |||
| 531 | ts = kzalloc(sizeof(*ts) + xfer_buf_size, GFP_KERNEL); | ||
| 532 | input_dev = input_allocate_device(); | ||
| 533 | if (!ts || !input_dev) { | ||
| 534 | error = -ENOMEM; | ||
| 535 | goto err_free_mem; | ||
| 536 | } | ||
| 537 | |||
| 538 | ts->dev = dev; | ||
| 539 | ts->input = input_dev; | ||
| 540 | ts->pdata = dev->platform_data; | ||
| 541 | ts->bus_ops = bus_ops; | ||
| 542 | ts->irq = irq; | ||
| 543 | |||
| 544 | init_completion(&ts->bl_ready); | ||
| 545 | snprintf(ts->phys, sizeof(ts->phys), "%s/input0", dev_name(dev)); | ||
| 546 | |||
| 547 | if (pdata->init) { | ||
| 548 | error = pdata->init(); | ||
| 549 | if (error) { | ||
| 550 | dev_err(ts->dev, "platform init failed, err: %d\n", | ||
| 551 | error); | ||
| 552 | goto err_free_mem; | ||
| 553 | } | ||
| 554 | } | ||
| 555 | |||
| 556 | input_dev->name = pdata->name; | ||
| 557 | input_dev->phys = ts->phys; | ||
| 558 | input_dev->id.bustype = bus_ops->bustype; | ||
| 559 | input_dev->dev.parent = ts->dev; | ||
| 560 | |||
| 561 | input_dev->open = cyttsp_open; | ||
| 562 | input_dev->close = cyttsp_close; | ||
| 563 | |||
| 564 | input_set_drvdata(input_dev, ts); | ||
| 565 | |||
| 566 | __set_bit(EV_ABS, input_dev->evbit); | ||
| 567 | input_set_abs_params(input_dev, ABS_MT_POSITION_X, | ||
| 568 | 0, pdata->maxx, 0, 0); | ||
| 569 | input_set_abs_params(input_dev, ABS_MT_POSITION_Y, | ||
| 570 | 0, pdata->maxy, 0, 0); | ||
| 571 | input_set_abs_params(input_dev, ABS_MT_TOUCH_MAJOR, | ||
| 572 | 0, CY_MAXZ, 0, 0); | ||
| 573 | |||
| 574 | input_mt_init_slots(input_dev, CY_MAX_ID, 0); | ||
| 575 | |||
| 576 | error = request_threaded_irq(ts->irq, NULL, cyttsp_irq, | ||
| 577 | IRQF_TRIGGER_FALLING | IRQF_ONESHOT, | ||
| 578 | pdata->name, ts); | ||
| 579 | if (error) { | ||
| 580 | dev_err(ts->dev, "failed to request IRQ %d, err: %d\n", | ||
| 581 | ts->irq, error); | ||
| 582 | goto err_platform_exit; | ||
| 583 | } | ||
| 584 | |||
| 585 | disable_irq(ts->irq); | ||
| 586 | |||
| 587 | error = cyttsp_power_on(ts); | ||
| 588 | if (error) | ||
| 589 | goto err_free_irq; | ||
| 590 | |||
| 591 | error = input_register_device(input_dev); | ||
| 592 | if (error) { | ||
| 593 | dev_err(ts->dev, "failed to register input device: %d\n", | ||
| 594 | error); | ||
| 595 | goto err_free_irq; | ||
| 596 | } | ||
| 597 | |||
| 598 | return ts; | ||
| 599 | |||
| 600 | err_free_irq: | ||
| 601 | free_irq(ts->irq, ts); | ||
| 602 | err_platform_exit: | ||
| 603 | if (pdata->exit) | ||
| 604 | pdata->exit(); | ||
| 605 | err_free_mem: | ||
| 606 | input_free_device(input_dev); | ||
| 607 | kfree(ts); | ||
| 608 | err_out: | ||
| 609 | return ERR_PTR(error); | ||
| 610 | } | ||
| 611 | EXPORT_SYMBOL_GPL(cyttsp_probe); | ||
| 612 | |||
| 613 | void cyttsp_remove(struct cyttsp *ts) | ||
| 614 | { | ||
| 615 | free_irq(ts->irq, ts); | ||
| 616 | input_unregister_device(ts->input); | ||
| 617 | if (ts->pdata->exit) | ||
| 618 | ts->pdata->exit(); | ||
| 619 | kfree(ts); | ||
| 620 | } | ||
| 621 | EXPORT_SYMBOL_GPL(cyttsp_remove); | ||
| 622 | |||
| 623 | MODULE_LICENSE("GPL"); | ||
| 624 | MODULE_DESCRIPTION("Cypress TrueTouch(R) Standard touchscreen driver core"); | ||
| 625 | MODULE_AUTHOR("Cypress"); | ||
diff --git a/drivers/input/touchscreen/cyttsp_core.h b/drivers/input/touchscreen/cyttsp_core.h deleted file mode 100644 index 1aa3c6967e7..00000000000 --- a/drivers/input/touchscreen/cyttsp_core.h +++ /dev/null | |||
| @@ -1,149 +0,0 @@ | |||
| 1 | /* | ||
| 2 | * Header file for: | ||
| 3 | * Cypress TrueTouch(TM) Standard Product (TTSP) touchscreen drivers. | ||
| 4 | * For use with Cypress Txx3xx parts. | ||
| 5 | * Supported parts include: | ||
| 6 | * CY8CTST341 | ||
| 7 | * CY8CTMA340 | ||
| 8 | * | ||
| 9 | * Copyright (C) 2009, 2010, 2011 Cypress Semiconductor, Inc. | ||
| 10 | * Copyright (C) 2012 Javier Martinez Canillas <javier@dowhile0.org> | ||
| 11 | * | ||
| 12 | * This program is free software; you can redistribute it and/or | ||
| 13 | * modify it under the terms of the GNU General Public License | ||
| 14 | * version 2, and only version 2, as published by the | ||
| 15 | * Free Software Foundation. | ||
| 16 | * | ||
| 17 | * This program is distributed in the hope that it will be useful, | ||
| 18 | * but WITHOUT ANY WARRANTY; without even the implied warranty of | ||
| 19 | * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the | ||
| 20 | * GNU General Public License for more details. | ||
| 21 | * | ||
| 22 | * You should have received a copy of the GNU General Public License along | ||
| 23 | * with this program; if not, write to the Free Software Foundation, Inc., | ||
| 24 | * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. | ||
| 25 | * | ||
| 26 | * Contact Cypress Semiconductor at www.cypress.com <kev@cypress.com> | ||
| 27 | * | ||
| 28 | */ | ||
| 29 | |||
| 30 | |||
| 31 | #ifndef __CYTTSP_CORE_H__ | ||
| 32 | #define __CYTTSP_CORE_H__ | ||
| 33 | |||
| 34 | #include <linux/kernel.h> | ||
| 35 | #include <linux/err.h> | ||
| 36 | #include <linux/module.h> | ||
| 37 | #include <linux/types.h> | ||
| 38 | #include <linux/device.h> | ||
| 39 | #include <linux/input/cyttsp.h> | ||
| 40 | |||
| 41 | #define CY_NUM_RETRY 16 /* max number of retries for read ops */ | ||
| 42 | |||
| 43 | struct cyttsp_tch { | ||
| 44 | __be16 x, y; | ||
| 45 | u8 z; | ||
| 46 | } __packed; | ||
| 47 | |||
| 48 | /* TrueTouch Standard Product Gen3 interface definition */ | ||
| 49 | struct cyttsp_xydata { | ||
| 50 | u8 hst_mode; | ||
| 51 | u8 tt_mode; | ||
| 52 | u8 tt_stat; | ||
| 53 | struct cyttsp_tch tch1; | ||
| 54 | u8 touch12_id; | ||
| 55 | struct cyttsp_tch tch2; | ||
| 56 | u8 gest_cnt; | ||
| 57 | u8 gest_id; | ||
| 58 | struct cyttsp_tch tch3; | ||
| 59 | u8 touch34_id; | ||
| 60 | struct cyttsp_tch tch4; | ||
| 61 | u8 tt_undef[3]; | ||
| 62 | u8 act_dist; | ||
| 63 | u8 tt_reserved; | ||
| 64 | } __packed; | ||
| 65 | |||
| 66 | |||
| 67 | /* TTSP System Information interface definition */ | ||
| 68 | struct cyttsp_sysinfo_data { | ||
| 69 | u8 hst_mode; | ||
| 70 | u8 mfg_cmd; | ||
| 71 | u8 mfg_stat; | ||
| 72 | u8 cid[3]; | ||
| 73 | u8 tt_undef1; | ||
| 74 | u8 uid[8]; | ||
| 75 | u8 bl_verh; | ||
| 76 | u8 bl_verl; | ||
| 77 | u8 tts_verh; | ||
| 78 | u8 tts_verl; | ||
| 79 | u8 app_idh; | ||
| 80 | u8 app_idl; | ||
| 81 | u8 app_verh; | ||
| 82 | u8 app_verl; | ||
| 83 | u8 tt_undef[5]; | ||
| 84 | u8 scn_typ; | ||
| 85 | u8 act_intrvl; | ||
| 86 | u8 tch_tmout; | ||
| 87 | u8 lp_intrvl; | ||
| 88 | }; | ||
| 89 | |||
| 90 | /* TTSP Bootloader Register Map interface definition */ | ||
| 91 | #define CY_BL_CHKSUM_OK 0x01 | ||
| 92 | struct cyttsp_bootloader_data { | ||
| 93 | u8 bl_file; | ||
| 94 | u8 bl_status; | ||
| 95 | u8 bl_error; | ||
| 96 | u8 blver_hi; | ||
| 97 | u8 blver_lo; | ||
| 98 | u8 bld_blver_hi; | ||
| 99 | u8 bld_blver_lo; | ||
| 100 | u8 ttspver_hi; | ||
| 101 | u8 ttspver_lo; | ||
| 102 | u8 appid_hi; | ||
| 103 | u8 appid_lo; | ||
| 104 | u8 appver_hi; | ||
| 105 | u8 appver_lo; | ||
| 106 | u8 cid_0; | ||
| 107 | u8 cid_1; | ||
| 108 | u8 cid_2; | ||
| 109 | }; | ||
| 110 | |||
| 111 | struct cyttsp; | ||
| 112 | |||
| 113 | struct cyttsp_bus_ops { | ||
| 114 | u16 bustype; | ||
| 115 | int (*write)(struct cyttsp *ts, | ||
| 116 | u8 addr, u8 length, const void *values); | ||
| 117 | int (*read)(struct cyttsp *ts, u8 addr, u8 length, void *values); | ||
| 118 | }; | ||
| 119 | |||
| 120 | enum cyttsp_state { | ||
| 121 | CY_IDLE_STATE, | ||
| 122 | CY_ACTIVE_STATE, | ||
| 123 | CY_BL_STATE, | ||
| 124 | }; | ||
| 125 | |||
| 126 | struct cyttsp { | ||
| 127 | struct device *dev; | ||
| 128 | int irq; | ||
| 129 | struct input_dev *input; | ||
| 130 | char phys[32]; | ||
| 131 | const struct cyttsp_platform_data *pdata; | ||
| 132 | const struct cyttsp_bus_ops *bus_ops; | ||
| 133 | struct cyttsp_bootloader_data bl_data; | ||
| 134 | struct cyttsp_sysinfo_data sysinfo_data; | ||
| 135 | struct cyttsp_xydata xy_data; | ||
| 136 | struct completion bl_ready; | ||
| 137 | enum cyttsp_state state; | ||
| 138 | bool suspended; | ||
| 139 | |||
| 140 | u8 xfer_buf[] ____cacheline_aligned; | ||
| 141 | }; | ||
| 142 | |||
| 143 | struct cyttsp *cyttsp_probe(const struct cyttsp_bus_ops *bus_ops, | ||
| 144 | struct device *dev, int irq, size_t xfer_buf_size); | ||
| 145 | void cyttsp_remove(struct cyttsp *ts); | ||
| 146 | |||
| 147 | extern const struct dev_pm_ops cyttsp_pm_ops; | ||
| 148 | |||
| 149 | #endif /* __CYTTSP_CORE_H__ */ | ||
diff --git a/drivers/input/touchscreen/cyttsp_i2c.c b/drivers/input/touchscreen/cyttsp_i2c.c deleted file mode 100644 index 4dbdf44b8fc..00000000000 --- a/drivers/input/touchscreen/cyttsp_i2c.c +++ /dev/null | |||
| @@ -1,136 +0,0 @@ | |||
| 1 | /* | ||
| 2 | * Source for: | ||
| 3 | * Cypress TrueTouch(TM) Standard Product (TTSP) I2C touchscreen driver. | ||
| 4 | * For use with Cypress Txx3xx parts. | ||
| 5 | * Supported parts include: | ||
| 6 | * CY8CTST341 | ||
| 7 | * CY8CTMA340 | ||
| 8 | * | ||
| 9 | * Copyright (C) 2009, 2010, 2011 Cypress Semiconductor, Inc. | ||
| 10 | * Copyright (C) 2012 Javier Martinez Canillas <javier@dowhile0.org> | ||
| 11 | * | ||
| 12 | * This program is free software; you can redistribute it and/or | ||
| 13 | * modify it under the terms of the GNU General Public License | ||
| 14 | * version 2, and only version 2, as published by the | ||
| 15 | * Free Software Foundation. | ||
| 16 | * | ||
| 17 | * This program is distributed in the hope that it will be useful, | ||
| 18 | * but WITHOUT ANY WARRANTY; without even the implied warranty of | ||
| 19 | * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the | ||
| 20 | * GNU General Public License for more details. | ||
| 21 | * | ||
| 22 | * You should have received a copy of the GNU General Public License along | ||
| 23 | * with this program; if not, write to the Free Software Foundation, Inc., | ||
| 24 | * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. | ||
| 25 | * | ||
| 26 | * Contact Cypress Semiconductor at www.cypress.com <kev@cypress.com> | ||
| 27 | * | ||
| 28 | */ | ||
| 29 | |||
| 30 | #include "cyttsp_core.h" | ||
| 31 | |||
| 32 | #include <linux/i2c.h> | ||
| 33 | #include <linux/input.h> | ||
| 34 | |||
| 35 | #define CY_I2C_DATA_SIZE 128 | ||
| 36 | |||
| 37 | static int cyttsp_i2c_read_block_data(struct cyttsp *ts, | ||
| 38 | u8 addr, u8 length, void *values) | ||
| 39 | { | ||
| 40 | struct i2c_client *client = to_i2c_client(ts->dev); | ||
| 41 | struct i2c_msg msgs[] = { | ||
| 42 | { | ||
| 43 | .addr = client->addr, | ||
| 44 | .flags = 0, | ||
| 45 | .len = 1, | ||
| 46 | .buf = &addr, | ||
| 47 | }, | ||
| 48 | { | ||
| 49 | .addr = client->addr, | ||
| 50 | .flags = I2C_M_RD, | ||
| 51 | .len = length, | ||
| 52 | .buf = values, | ||
| 53 | }, | ||
| 54 | }; | ||
| 55 | int retval; | ||
| 56 | |||
| 57 | retval = i2c_transfer(client->adapter, msgs, ARRAY_SIZE(msgs)); | ||
| 58 | if (retval < 0) | ||
| 59 | return retval; | ||
| 60 | |||
| 61 | return retval != ARRAY_SIZE(msgs) ? -EIO : 0; | ||
| 62 | } | ||
| 63 | |||
| 64 | static int cyttsp_i2c_write_block_data(struct cyttsp *ts, | ||
| 65 | u8 addr, u8 length, const void *values) | ||
| 66 | { | ||
| 67 | struct i2c_client *client = to_i2c_client(ts->dev); | ||
| 68 | int retval; | ||
| 69 | |||
| 70 | ts->xfer_buf[0] = addr; | ||
| 71 | memcpy(&ts->xfer_buf[1], values, length); | ||
| 72 | |||
| 73 | retval = i2c_master_send(client, ts->xfer_buf, length + 1); | ||
| 74 | |||
| 75 | return retval < 0 ? retval : 0; | ||
| 76 | } | ||
| 77 | |||
| 78 | static const struct cyttsp_bus_ops cyttsp_i2c_bus_ops = { | ||
| 79 | .bustype = BUS_I2C, | ||
| 80 | .write = cyttsp_i2c_write_block_data, | ||
| 81 | .read = cyttsp_i2c_read_block_data, | ||
| 82 | }; | ||
| 83 | |||
| 84 | static int cyttsp_i2c_probe(struct i2c_client *client, | ||
| 85 | const struct i2c_device_id *id) | ||
| 86 | { | ||
| 87 | struct cyttsp *ts; | ||
| 88 | |||
| 89 | if (!i2c_check_functionality(client->adapter, I2C_FUNC_I2C)) { | ||
| 90 | dev_err(&client->dev, "I2C functionality not Supported\n"); | ||
| 91 | return -EIO; | ||
| 92 | } | ||
| 93 | |||
| 94 | ts = cyttsp_probe(&cyttsp_i2c_bus_ops, &client->dev, client->irq, | ||
| 95 | CY_I2C_DATA_SIZE); | ||
| 96 | |||
| 97 | if (IS_ERR(ts)) | ||
| 98 | return PTR_ERR(ts); | ||
| 99 | |||
| 100 | i2c_set_clientdata(client, ts); | ||
| 101 | |||
| 102 | return 0; | ||
| 103 | } | ||
| 104 | |||
| 105 | static int cyttsp_i2c_remove(struct i2c_client *client) | ||
| 106 | { | ||
| 107 | struct cyttsp *ts = i2c_get_clientdata(client); | ||
| 108 | |||
| 109 | cyttsp_remove(ts); | ||
| 110 | |||
| 111 | return 0; | ||
| 112 | } | ||
| 113 | |||
| 114 | static const struct i2c_device_id cyttsp_i2c_id[] = { | ||
| 115 | { CY_I2C_NAME, 0 }, | ||
| 116 | { } | ||
| 117 | }; | ||
| 118 | MODULE_DEVICE_TABLE(i2c, cyttsp_i2c_id); | ||
| 119 | |||
| 120 | static struct i2c_driver cyttsp_i2c_driver = { | ||
| 121 | .driver = { | ||
| 122 | .name = CY_I2C_NAME, | ||
| 123 | .owner = THIS_MODULE, | ||
| 124 | .pm = &cyttsp_pm_ops, | ||
| 125 | }, | ||
| 126 | .probe = cyttsp_i2c_probe, | ||
| 127 | .remove = cyttsp_i2c_remove, | ||
| 128 | .id_table = cyttsp_i2c_id, | ||
| 129 | }; | ||
| 130 | |||
| 131 | module_i2c_driver(cyttsp_i2c_driver); | ||
| 132 | |||
| 133 | MODULE_LICENSE("GPL"); | ||
| 134 | MODULE_DESCRIPTION("Cypress TrueTouch(R) Standard Product (TTSP) I2C driver"); | ||
| 135 | MODULE_AUTHOR("Cypress"); | ||
| 136 | MODULE_ALIAS("i2c:cyttsp"); | ||
diff --git a/drivers/input/touchscreen/cyttsp_spi.c b/drivers/input/touchscreen/cyttsp_spi.c deleted file mode 100644 index 638e20310f1..00000000000 --- a/drivers/input/touchscreen/cyttsp_spi.c +++ /dev/null | |||
| @@ -1,200 +0,0 @@ | |||
| 1 | /* | ||
| 2 | * Source for: | ||
| 3 | * Cypress TrueTouch(TM) Standard Product (TTSP) SPI touchscreen driver. | ||
| 4 | * For use with Cypress Txx3xx parts. | ||
| 5 | * Supported parts include: | ||
| 6 | * CY8CTST341 | ||
| 7 | * CY8CTMA340 | ||
| 8 | * | ||
| 9 | * Copyright (C) 2009, 2010, 2011 Cypress Semiconductor, Inc. | ||
| 10 | * Copyright (C) 2012 Javier Martinez Canillas <javier@dowhile0.org> | ||
| 11 | * | ||
| 12 | * This program is free software; you can redistribute it and/or | ||
| 13 | * modify it under the terms of the GNU General Public License | ||
| 14 | * version 2, and only version 2, as published by the | ||
| 15 | * Free Software Foundation. | ||
| 16 | * | ||
| 17 | * This program is distributed in the hope that it will be useful, | ||
| 18 | * but WITHOUT ANY WARRANTY; without even the implied warranty of | ||
| 19 | * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the | ||
| 20 | * GNU General Public License for more details. | ||
| 21 | * | ||
| 22 | * You should have received a copy of the GNU General Public License along | ||
| 23 | * with this program; if not, write to the Free Software Foundation, Inc., | ||
| 24 | * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. | ||
| 25 | * | ||
| 26 | * Contact Cypress Semiconductor at www.cypress.com <kev@cypress.com> | ||
| 27 | * | ||
| 28 | */ | ||
| 29 | |||
| 30 | #include "cyttsp_core.h" | ||
| 31 | |||
| 32 | #include <linux/delay.h> | ||
| 33 | #include <linux/input.h> | ||
| 34 | #include <linux/spi/spi.h> | ||
| 35 | |||
| 36 | #define CY_SPI_WR_OP 0x00 /* r/~w */ | ||
| 37 | #define CY_SPI_RD_OP 0x01 | ||
| 38 | #define CY_SPI_CMD_BYTES 4 | ||
| 39 | #define CY_SPI_SYNC_BYTE 2 | ||
| 40 | #define CY_SPI_SYNC_ACK1 0x62 /* from protocol v.2 */ | ||
| 41 | #define CY_SPI_SYNC_ACK2 0x9D /* from protocol v.2 */ | ||
| 42 | #define CY_SPI_DATA_SIZE 128 | ||
| 43 | #define CY_SPI_DATA_BUF_SIZE (CY_SPI_CMD_BYTES + CY_SPI_DATA_SIZE) | ||
| 44 | #define CY_SPI_BITS_PER_WORD 8 | ||
| 45 | |||
| 46 | static int cyttsp_spi_xfer(struct cyttsp *ts, | ||
| 47 | u8 op, u8 reg, u8 *buf, int length) | ||
| 48 | { | ||
| 49 | struct spi_device *spi = to_spi_device(ts->dev); | ||
| 50 | struct spi_message msg; | ||
| 51 | struct spi_transfer xfer[2]; | ||
| 52 | u8 *wr_buf = &ts->xfer_buf[0]; | ||
| 53 | u8 *rd_buf = &ts->xfer_buf[CY_SPI_DATA_BUF_SIZE]; | ||
| 54 | int retval; | ||
| 55 | int i; | ||
| 56 | |||
| 57 | if (length > CY_SPI_DATA_SIZE) { | ||
| 58 | dev_err(ts->dev, "%s: length %d is too big.\n", | ||
| 59 | __func__, length); | ||
| 60 | return -EINVAL; | ||
| 61 | } | ||
| 62 | |||
| 63 | memset(wr_buf, 0, CY_SPI_DATA_BUF_SIZE); | ||
| 64 | memset(rd_buf, 0, CY_SPI_DATA_BUF_SIZE); | ||
| 65 | |||
| 66 | wr_buf[0] = 0x00; /* header byte 0 */ | ||
| 67 | wr_buf[1] = 0xFF; /* header byte 1 */ | ||
| 68 | wr_buf[2] = reg; /* reg index */ | ||
| 69 | wr_buf[3] = op; /* r/~w */ | ||
| 70 | if (op == CY_SPI_WR_OP) | ||
| 71 | memcpy(wr_buf + CY_SPI_CMD_BYTES, buf, length); | ||
| 72 | |||
| 73 | memset(xfer, 0, sizeof(xfer)); | ||
| 74 | spi_message_init(&msg); | ||
| 75 | |||
| 76 | /* | ||
| 77 | We set both TX and RX buffers because Cypress TTSP | ||
| 78 | requires full duplex operation. | ||
| 79 | */ | ||
| 80 | xfer[0].tx_buf = wr_buf; | ||
| 81 | xfer[0].rx_buf = rd_buf; | ||
| 82 | switch (op) { | ||
| 83 | case CY_SPI_WR_OP: | ||
| 84 | xfer[0].len = length + CY_SPI_CMD_BYTES; | ||
| 85 | spi_message_add_tail(&xfer[0], &msg); | ||
| 86 | break; | ||
| 87 | |||
| 88 | case CY_SPI_RD_OP: | ||
| 89 | xfer[0].len = CY_SPI_CMD_BYTES; | ||
| 90 | spi_message_add_tail(&xfer[0], &msg); | ||
| 91 | |||
| 92 | xfer[1].rx_buf = buf; | ||
| 93 | xfer[1].len = length; | ||
| 94 | spi_message_add_tail(&xfer[1], &msg); | ||
| 95 | break; | ||
| 96 | |||
| 97 | default: | ||
| 98 | dev_err(ts->dev, "%s: bad operation code=%d\n", __func__, op); | ||
| 99 | return -EINVAL; | ||
| 100 | } | ||
| 101 | |||
| 102 | retval = spi_sync(spi, &msg); | ||
| 103 | if (retval < 0) { | ||
| 104 | dev_dbg(ts->dev, "%s: spi_sync() error %d, len=%d, op=%d\n", | ||
| 105 | __func__, retval, xfer[1].len, op); | ||
| 106 | |||
| 107 | /* | ||
| 108 | * do not return here since was a bad ACK sequence | ||
| 109 | * let the following ACK check handle any errors and | ||
| 110 | * allow silent retries | ||
| 111 | */ | ||
| 112 | } | ||
| 113 | |||
| 114 | if (rd_buf[CY_SPI_SYNC_BYTE] != CY_SPI_SYNC_ACK1 || | ||
| 115 | rd_buf[CY_SPI_SYNC_BYTE + 1] != CY_SPI_SYNC_ACK2) { | ||
| 116 | |||
| 117 | dev_dbg(ts->dev, "%s: operation %d failed\n", __func__, op); | ||
| 118 | |||
| 119 | for (i = 0; i < CY_SPI_CMD_BYTES; i++) | ||
| 120 | dev_dbg(ts->dev, "%s: test rd_buf[%d]:0x%02x\n", | ||
| 121 | __func__, i, rd_buf[i]); | ||
| 122 | for (i = 0; i < length; i++) | ||
| 123 | dev_dbg(ts->dev, "%s: test buf[%d]:0x%02x\n", | ||
| 124 | __func__, i, buf[i]); | ||
| 125 | |||
| 126 | return -EIO; | ||
| 127 | } | ||
| 128 | |||
| 129 | return 0; | ||
| 130 | } | ||
| 131 | |||
| 132 | static int cyttsp_spi_read_block_data(struct cyttsp *ts, | ||
| 133 | u8 addr, u8 length, void *data) | ||
| 134 | { | ||
| 135 | return cyttsp_spi_xfer(ts, CY_SPI_RD_OP, addr, data, length); | ||
| 136 | } | ||
| 137 | |||
| 138 | static int cyttsp_spi_write_block_data(struct cyttsp *ts, | ||
| 139 | u8 addr, u8 length, const void *data) | ||
| 140 | { | ||
| 141 | return cyttsp_spi_xfer(ts, CY_SPI_WR_OP, addr, (void *)data, length); | ||
| 142 | } | ||
| 143 | |||
| 144 | static const struct cyttsp_bus_ops cyttsp_spi_bus_ops = { | ||
| 145 | .bustype = BUS_SPI, | ||
| 146 | .write = cyttsp_spi_write_block_data, | ||
| 147 | .read = cyttsp_spi_read_block_data, | ||
| 148 | }; | ||
| 149 | |||
| 150 | static int cyttsp_spi_probe(struct spi_device *spi) | ||
| 151 | { | ||
| 152 | struct cyttsp *ts; | ||
| 153 | int error; | ||
| 154 | |||
| 155 | /* Set up SPI*/ | ||
| 156 | spi->bits_per_word = CY_SPI_BITS_PER_WORD; | ||
| 157 | spi->mode = SPI_MODE_0; | ||
| 158 | error = spi_setup(spi); | ||
| 159 | if (error < 0) { | ||
| 160 | dev_err(&spi->dev, "%s: SPI setup error %d\n", | ||
| 161 | __func__, error); | ||
| 162 | return error; | ||
| 163 | } | ||
| 164 | |||
| 165 | ts = cyttsp_probe(&cyttsp_spi_bus_ops, &spi->dev, spi->irq, | ||
| 166 | CY_SPI_DATA_BUF_SIZE * 2); | ||
| 167 | if (IS_ERR(ts)) | ||
| 168 | return PTR_ERR(ts); | ||
| 169 | |||
| 170 | spi_set_drvdata(spi, ts); | ||
| 171 | |||
| 172 | return 0; | ||
| 173 | } | ||
| 174 | |||
| 175 | static int cyttsp_spi_remove(struct spi_device *spi) | ||
| 176 | { | ||
| 177 | struct cyttsp *ts = spi_get_drvdata(spi); | ||
| 178 | |||
| 179 | cyttsp_remove(ts); | ||
| 180 | |||
| 181 | return 0; | ||
| 182 | } | ||
| 183 | |||
| 184 | static struct spi_driver cyttsp_spi_driver = { | ||
| 185 | .driver = { | ||
| 186 | .name = CY_SPI_NAME, | ||
| 187 | .owner = THIS_MODULE, | ||
| 188 | .pm = &cyttsp_pm_ops, | ||
| 189 | }, | ||
| 190 | .probe = cyttsp_spi_probe, | ||
| 191 | .remove = cyttsp_spi_remove, | ||
| 192 | }; | ||
| 193 | |||
| 194 | module_spi_driver(cyttsp_spi_driver); | ||
| 195 | |||
| 196 | MODULE_ALIAS("spi:cyttsp"); | ||
| 197 | MODULE_LICENSE("GPL"); | ||
| 198 | MODULE_DESCRIPTION("Cypress TrueTouch(R) Standard Product (TTSP) SPI driver"); | ||
| 199 | MODULE_AUTHOR("Cypress"); | ||
| 200 | MODULE_ALIAS("spi:cyttsp"); | ||
diff --git a/drivers/input/touchscreen/da9034-ts.c b/drivers/input/touchscreen/da9034-ts.c index 34ad84105e6..2b72a5923c1 100644 --- a/drivers/input/touchscreen/da9034-ts.c +++ b/drivers/input/touchscreen/da9034-ts.c | |||
| @@ -297,7 +297,7 @@ static void da9034_touch_close(struct input_dev *dev) | |||
| 297 | } | 297 | } |
| 298 | 298 | ||
| 299 | 299 | ||
| 300 | static int da9034_touch_probe(struct platform_device *pdev) | 300 | static int __devinit da9034_touch_probe(struct platform_device *pdev) |
| 301 | { | 301 | { |
| 302 | struct da9034_touch_pdata *pdata = pdev->dev.platform_data; | 302 | struct da9034_touch_pdata *pdata = pdev->dev.platform_data; |
| 303 | struct da9034_touch *touch; | 303 | struct da9034_touch *touch; |
| @@ -361,7 +361,7 @@ err_free_touch: | |||
| 361 | return ret; | 361 | return ret; |
| 362 | } | 362 | } |
| 363 | 363 | ||
| 364 | static int da9034_touch_remove(struct platform_device *pdev) | 364 | static int __devexit da9034_touch_remove(struct platform_device *pdev) |
| 365 | { | 365 | { |
| 366 | struct da9034_touch *touch = platform_get_drvdata(pdev); | 366 | struct da9034_touch *touch = platform_get_drvdata(pdev); |
| 367 | 367 | ||
| @@ -377,9 +377,20 @@ static struct platform_driver da9034_touch_driver = { | |||
| 377 | .owner = THIS_MODULE, | 377 | .owner = THIS_MODULE, |
| 378 | }, | 378 | }, |
| 379 | .probe = da9034_touch_probe, | 379 | .probe = da9034_touch_probe, |
| 380 | .remove = da9034_touch_remove, | 380 | .remove = __devexit_p(da9034_touch_remove), |
| 381 | }; | 381 | }; |
| 382 | module_platform_driver(da9034_touch_driver); | 382 | |
| 383 | static int __init da9034_touch_init(void) | ||
| 384 | { | ||
| 385 | return platform_driver_register(&da9034_touch_driver); | ||
| 386 | } | ||
| 387 | module_init(da9034_touch_init); | ||
| 388 | |||
| 389 | static void __exit da9034_touch_exit(void) | ||
| 390 | { | ||
| 391 | platform_driver_unregister(&da9034_touch_driver); | ||
| 392 | } | ||
| 393 | module_exit(da9034_touch_exit); | ||
| 383 | 394 | ||
| 384 | MODULE_DESCRIPTION("Touchscreen driver for Dialog Semiconductor DA9034"); | 395 | MODULE_DESCRIPTION("Touchscreen driver for Dialog Semiconductor DA9034"); |
| 385 | MODULE_AUTHOR("Eric Miao <eric.miao@marvell.com>, Bin Yang <bin.yang@marvell.com>"); | 396 | MODULE_AUTHOR("Eric Miao <eric.miao@marvell.com>, Bin Yang <bin.yang@marvell.com>"); |
diff --git a/drivers/input/touchscreen/da9052_tsi.c b/drivers/input/touchscreen/da9052_tsi.c deleted file mode 100644 index 8f561e22bdd..00000000000 --- a/drivers/input/touchscreen/da9052_tsi.c +++ /dev/null | |||
| @@ -1,351 +0,0 @@ | |||
| 1 | /* | ||
| 2 | * TSI driver for Dialog DA9052 | ||
| 3 | * | ||
| 4 | * Copyright(c) 2012 Dialog Semiconductor Ltd. | ||
| 5 | * | ||
| 6 | * Author: David Dajun Chen <dchen@diasemi.com> | ||
| 7 | * | ||
| 8 | * This program is free software; you can redistribute it and/or modify it | ||
| 9 | * under the terms of the GNU General Public License as published by the | ||
| 10 | * Free Software Foundation; either version 2 of the License, or (at your | ||
| 11 | * option) any later version. | ||
| 12 | * | ||
| 13 | */ | ||
| 14 | #include <linux/module.h> | ||
| 15 | #include <linux/input.h> | ||
| 16 | #include <linux/delay.h> | ||
| 17 | #include <linux/platform_device.h> | ||
| 18 | #include <linux/interrupt.h> | ||
| 19 | |||
| 20 | #include <linux/mfd/da9052/reg.h> | ||
| 21 | #include <linux/mfd/da9052/da9052.h> | ||
| 22 | |||
| 23 | #define TSI_PEN_DOWN_STATUS 0x40 | ||
| 24 | |||
| 25 | struct da9052_tsi { | ||
| 26 | struct da9052 *da9052; | ||
| 27 | struct input_dev *dev; | ||
| 28 | struct delayed_work ts_pen_work; | ||
| 29 | struct mutex mutex; | ||
| 30 | bool stopped; | ||
| 31 | bool adc_on; | ||
| 32 | }; | ||
| 33 | |||
| 34 | static void da9052_ts_adc_toggle(struct da9052_tsi *tsi, bool on) | ||
| 35 | { | ||
| 36 | da9052_reg_update(tsi->da9052, DA9052_TSI_CONT_A_REG, 1 << 0, on); | ||
| 37 | tsi->adc_on = on; | ||
| 38 | } | ||
| 39 | |||
| 40 | static irqreturn_t da9052_ts_pendwn_irq(int irq, void *data) | ||
| 41 | { | ||
| 42 | struct da9052_tsi *tsi = data; | ||
| 43 | |||
| 44 | if (!tsi->stopped) { | ||
| 45 | /* Mask PEN_DOWN event and unmask TSI_READY event */ | ||
| 46 | da9052_disable_irq_nosync(tsi->da9052, DA9052_IRQ_PENDOWN); | ||
| 47 | da9052_enable_irq(tsi->da9052, DA9052_IRQ_TSIREADY); | ||
| 48 | |||
| 49 | da9052_ts_adc_toggle(tsi, true); | ||
| 50 | |||
| 51 | schedule_delayed_work(&tsi->ts_pen_work, HZ / 50); | ||
| 52 | } | ||
| 53 | |||
| 54 | return IRQ_HANDLED; | ||
| 55 | } | ||
| 56 | |||
| 57 | static void da9052_ts_read(struct da9052_tsi *tsi) | ||
| 58 | { | ||
| 59 | struct input_dev *input = tsi->dev; | ||
| 60 | int ret; | ||
| 61 | u16 x, y, z; | ||
| 62 | u8 v; | ||
| 63 | |||
| 64 | ret = da9052_reg_read(tsi->da9052, DA9052_TSI_X_MSB_REG); | ||
| 65 | if (ret < 0) | ||
| 66 | return; | ||
| 67 | |||
| 68 | x = (u16) ret; | ||
| 69 | |||
| 70 | ret = da9052_reg_read(tsi->da9052, DA9052_TSI_Y_MSB_REG); | ||
| 71 | if (ret < 0) | ||
| 72 | return; | ||
| 73 | |||
| 74 | y = (u16) ret; | ||
| 75 | |||
| 76 | ret = da9052_reg_read(tsi->da9052, DA9052_TSI_Z_MSB_REG); | ||
| 77 | if (ret < 0) | ||
| 78 | return; | ||
| 79 | |||
| 80 | z = (u16) ret; | ||
| 81 | |||
| 82 | ret = da9052_reg_read(tsi->da9052, DA9052_TSI_LSB_REG); | ||
| 83 | if (ret < 0) | ||
| 84 | return; | ||
| 85 | |||
| 86 | v = (u8) ret; | ||
| 87 | |||
| 88 | x = ((x << 2) & 0x3fc) | (v & 0x3); | ||
| 89 | y = ((y << 2) & 0x3fc) | ((v & 0xc) >> 2); | ||
| 90 | z = ((z << 2) & 0x3fc) | ((v & 0x30) >> 4); | ||
| 91 | |||
| 92 | input_report_key(input, BTN_TOUCH, 1); | ||
| 93 | input_report_abs(input, ABS_X, x); | ||
| 94 | input_report_abs(input, ABS_Y, y); | ||
| 95 | input_report_abs(input, ABS_PRESSURE, z); | ||
| 96 | input_sync(input); | ||
| 97 | } | ||
| 98 | |||
| 99 | static irqreturn_t da9052_ts_datardy_irq(int irq, void *data) | ||
| 100 | { | ||
| 101 | struct da9052_tsi *tsi = data; | ||
| 102 | |||
| 103 | da9052_ts_read(tsi); | ||
| 104 | |||
| 105 | return IRQ_HANDLED; | ||
| 106 | } | ||
| 107 | |||
| 108 | static void da9052_ts_pen_work(struct work_struct *work) | ||
| 109 | { | ||
| 110 | struct da9052_tsi *tsi = container_of(work, struct da9052_tsi, | ||
| 111 | ts_pen_work.work); | ||
| 112 | if (!tsi->stopped) { | ||
| 113 | int ret = da9052_reg_read(tsi->da9052, DA9052_TSI_LSB_REG); | ||
| 114 | if (ret < 0 || (ret & TSI_PEN_DOWN_STATUS)) { | ||
| 115 | /* Pen is still DOWN (or read error) */ | ||
| 116 | schedule_delayed_work(&tsi->ts_pen_work, HZ / 50); | ||
| 117 | } else { | ||
| 118 | struct input_dev *input = tsi->dev; | ||
| 119 | |||
| 120 | /* Pen UP */ | ||
| 121 | da9052_ts_adc_toggle(tsi, false); | ||
| 122 | |||
| 123 | /* Report Pen UP */ | ||
| 124 | input_report_key(input, BTN_TOUCH, 0); | ||
| 125 | input_report_abs(input, ABS_PRESSURE, 0); | ||
| 126 | input_sync(input); | ||
| 127 | |||
| 128 | /* | ||
| 129 | * FIXME: Fixes the unhandled irq issue when quick | ||
| 130 | * pen down and pen up events occurs | ||
| 131 | */ | ||
| 132 | ret = da9052_reg_update(tsi->da9052, | ||
| 133 | DA9052_EVENT_B_REG, 0xC0, 0xC0); | ||
| 134 | if (ret < 0) | ||
| 135 | return; | ||
| 136 | |||
| 137 | /* Mask TSI_READY event and unmask PEN_DOWN event */ | ||
| 138 | da9052_disable_irq(tsi->da9052, DA9052_IRQ_TSIREADY); | ||
| 139 | da9052_enable_irq(tsi->da9052, DA9052_IRQ_PENDOWN); | ||
| 140 | } | ||
| 141 | } | ||
| 142 | } | ||
| 143 | |||
| 144 | static int da9052_ts_configure_gpio(struct da9052 *da9052) | ||
| 145 | { | ||
| 146 | int error; | ||
| 147 | |||
| 148 | error = da9052_reg_update(da9052, DA9052_GPIO_2_3_REG, 0x30, 0); | ||
| 149 | if (error < 0) | ||
| 150 | return error; | ||
| 151 | |||
| 152 | error = da9052_reg_update(da9052, DA9052_GPIO_4_5_REG, 0x33, 0); | ||
| 153 | if (error < 0) | ||
| 154 | return error; | ||
| 155 | |||
| 156 | error = da9052_reg_update(da9052, DA9052_GPIO_6_7_REG, 0x33, 0); | ||
| 157 | if (error < 0) | ||
| 158 | return error; | ||
| 159 | |||
| 160 | return 0; | ||
| 161 | } | ||
| 162 | |||
| 163 | static int da9052_configure_tsi(struct da9052_tsi *tsi) | ||
| 164 | { | ||
| 165 | int error; | ||
| 166 | |||
| 167 | error = da9052_ts_configure_gpio(tsi->da9052); | ||
| 168 | if (error) | ||
| 169 | return error; | ||
| 170 | |||
| 171 | /* Measure TSI sample every 1ms */ | ||
| 172 | error = da9052_reg_update(tsi->da9052, DA9052_ADC_CONT_REG, | ||
| 173 | 1 << 6, 1 << 6); | ||
| 174 | if (error < 0) | ||
| 175 | return error; | ||
| 176 | |||
| 177 | /* TSI_DELAY: 3 slots, TSI_SKIP: 0 slots, TSI_MODE: XYZP */ | ||
| 178 | error = da9052_reg_update(tsi->da9052, DA9052_TSI_CONT_A_REG, 0xFC, 0xC0); | ||
| 179 | if (error < 0) | ||
| 180 | return error; | ||
| 181 | |||
| 182 | /* Supply TSIRef through LD09 */ | ||
| 183 | error = da9052_reg_write(tsi->da9052, DA9052_LDO9_REG, 0x59); | ||
| 184 | if (error < 0) | ||
| 185 | return error; | ||
| 186 | |||
| 187 | return 0; | ||
| 188 | } | ||
| 189 | |||
| 190 | static int da9052_ts_input_open(struct input_dev *input_dev) | ||
| 191 | { | ||
| 192 | struct da9052_tsi *tsi = input_get_drvdata(input_dev); | ||
| 193 | |||
| 194 | tsi->stopped = false; | ||
| 195 | mb(); | ||
| 196 | |||
| 197 | /* Unmask PEN_DOWN event */ | ||
| 198 | da9052_enable_irq(tsi->da9052, DA9052_IRQ_PENDOWN); | ||
| 199 | |||
| 200 | /* Enable Pen Detect Circuit */ | ||
| 201 | return da9052_reg_update(tsi->da9052, DA9052_TSI_CONT_A_REG, | ||
| 202 | 1 << 1, 1 << 1); | ||
| 203 | } | ||
| 204 | |||
| 205 | static void da9052_ts_input_close(struct input_dev *input_dev) | ||
| 206 | { | ||
| 207 | struct da9052_tsi *tsi = input_get_drvdata(input_dev); | ||
| 208 | |||
| 209 | tsi->stopped = true; | ||
| 210 | mb(); | ||
| 211 | da9052_disable_irq(tsi->da9052, DA9052_IRQ_PENDOWN); | ||
| 212 | cancel_delayed_work_sync(&tsi->ts_pen_work); | ||
| 213 | |||
| 214 | if (tsi->adc_on) { | ||
| 215 | da9052_disable_irq(tsi->da9052, DA9052_IRQ_TSIREADY); | ||
| 216 | da9052_ts_adc_toggle(tsi, false); | ||
| 217 | |||
| 218 | /* | ||
| 219 | * If ADC was on that means that pendwn IRQ was disabled | ||
| 220 | * twice and we need to enable it to keep enable/disable | ||
| 221 | * counter balanced. IRQ is still off though. | ||
| 222 | */ | ||
| 223 | da9052_enable_irq(tsi->da9052, DA9052_IRQ_PENDOWN); | ||
| 224 | } | ||
| 225 | |||
| 226 | /* Disable Pen Detect Circuit */ | ||
| 227 | da9052_reg_update(tsi->da9052, DA9052_TSI_CONT_A_REG, 1 << 1, 0); | ||
| 228 | } | ||
| 229 | |||
| 230 | static int da9052_ts_probe(struct platform_device *pdev) | ||
| 231 | { | ||
| 232 | struct da9052 *da9052; | ||
| 233 | struct da9052_tsi *tsi; | ||
| 234 | struct input_dev *input_dev; | ||
| 235 | int error; | ||
| 236 | |||
| 237 | da9052 = dev_get_drvdata(pdev->dev.parent); | ||
| 238 | if (!da9052) | ||
| 239 | return -EINVAL; | ||
| 240 | |||
| 241 | tsi = kzalloc(sizeof(struct da9052_tsi), GFP_KERNEL); | ||
| 242 | input_dev = input_allocate_device(); | ||
| 243 | if (!tsi || !input_dev) { | ||
| 244 | error = -ENOMEM; | ||
| 245 | goto err_free_mem; | ||
| 246 | } | ||
| 247 | |||
| 248 | tsi->da9052 = da9052; | ||
| 249 | tsi->dev = input_dev; | ||
| 250 | tsi->stopped = true; | ||
| 251 | INIT_DELAYED_WORK(&tsi->ts_pen_work, da9052_ts_pen_work); | ||
| 252 | |||
| 253 | input_dev->id.version = 0x0101; | ||
| 254 | input_dev->id.vendor = 0x15B6; | ||
| 255 | input_dev->id.product = 0x9052; | ||
| 256 | input_dev->name = "Dialog DA9052 TouchScreen Driver"; | ||
| 257 | input_dev->dev.parent = &pdev->dev; | ||
| 258 | input_dev->open = da9052_ts_input_open; | ||
| 259 | input_dev->close = da9052_ts_input_close; | ||
| 260 | |||
| 261 | __set_bit(EV_ABS, input_dev->evbit); | ||
| 262 | __set_bit(EV_KEY, input_dev->evbit); | ||
| 263 | __set_bit(BTN_TOUCH, input_dev->keybit); | ||
| 264 | |||
| 265 | input_set_abs_params(input_dev, ABS_X, 0, 1023, 0, 0); | ||
| 266 | input_set_abs_params(input_dev, ABS_Y, 0, 1023, 0, 0); | ||
| 267 | input_set_abs_params(input_dev, ABS_PRESSURE, 0, 1023, 0, 0); | ||
| 268 | |||
| 269 | input_set_drvdata(input_dev, tsi); | ||
| 270 | |||
| 271 | /* Disable Pen Detect Circuit */ | ||
| 272 | da9052_reg_update(tsi->da9052, DA9052_TSI_CONT_A_REG, 1 << 1, 0); | ||
| 273 | |||
| 274 | /* Disable ADC */ | ||
| 275 | da9052_ts_adc_toggle(tsi, false); | ||
| 276 | |||
| 277 | error = da9052_request_irq(tsi->da9052, DA9052_IRQ_PENDOWN, | ||
| 278 | "pendown-irq", da9052_ts_pendwn_irq, tsi); | ||
| 279 | if (error) { | ||
| 280 | dev_err(tsi->da9052->dev, | ||
| 281 | "Failed to register PENDWN IRQ: %d\n", error); | ||
| 282 | goto err_free_mem; | ||
| 283 | } | ||
| 284 | |||
| 285 | error = da9052_request_irq(tsi->da9052, DA9052_IRQ_TSIREADY, | ||
| 286 | "tsiready-irq", da9052_ts_datardy_irq, tsi); | ||
| 287 | if (error) { | ||
| 288 | dev_err(tsi->da9052->dev, | ||
| 289 | "Failed to register TSIRDY IRQ :%d\n", error); | ||
| 290 | goto err_free_pendwn_irq; | ||
| 291 | } | ||
| 292 | |||
| 293 | /* Mask PEN_DOWN and TSI_READY events */ | ||
| 294 | da9052_disable_irq(tsi->da9052, DA9052_IRQ_PENDOWN); | ||
| 295 | da9052_disable_irq(tsi->da9052, DA9052_IRQ_TSIREADY); | ||
| 296 | |||
| 297 | error = da9052_configure_tsi(tsi); | ||
| 298 | if (error) | ||
| 299 | goto err_free_datardy_irq; | ||
| 300 | |||
| 301 | error = input_register_device(tsi->dev); | ||
| 302 | if (error) | ||
| 303 | goto err_free_datardy_irq; | ||
| 304 | |||
| 305 | platform_set_drvdata(pdev, tsi); | ||
| 306 | |||
| 307 | return 0; | ||
| 308 | |||
| 309 | err_free_datardy_irq: | ||
| 310 | da9052_free_irq(tsi->da9052, DA9052_IRQ_TSIREADY, tsi); | ||
| 311 | err_free_pendwn_irq: | ||
| 312 | da9052_free_irq(tsi->da9052, DA9052_IRQ_PENDOWN, tsi); | ||
| 313 | err_free_mem: | ||
| 314 | kfree(tsi); | ||
| 315 | input_free_device(input_dev); | ||
| 316 | |||
| 317 | return error; | ||
| 318 | } | ||
| 319 | |||
| 320 | static int da9052_ts_remove(struct platform_device *pdev) | ||
| 321 | { | ||
| 322 | struct da9052_tsi *tsi = platform_get_drvdata(pdev); | ||
| 323 | |||
| 324 | da9052_reg_write(tsi->da9052, DA9052_LDO9_REG, 0x19); | ||
| 325 | |||
| 326 | da9052_free_irq(tsi->da9052, DA9052_IRQ_TSIREADY, tsi); | ||
| 327 | da9052_free_irq(tsi->da9052, DA9052_IRQ_PENDOWN, tsi); | ||
| 328 | |||
| 329 | input_unregister_device(tsi->dev); | ||
| 330 | kfree(tsi); | ||
| 331 | |||
| 332 | platform_set_drvdata(pdev, NULL); | ||
| 333 | |||
| 334 | return 0; | ||
| 335 | } | ||
| 336 | |||
| 337 | static struct platform_driver da9052_tsi_driver = { | ||
| 338 | .probe = da9052_ts_probe, | ||
| 339 | .remove = da9052_ts_remove, | ||
| 340 | .driver = { | ||
| 341 | .name = "da9052-tsi", | ||
| 342 | .owner = THIS_MODULE, | ||
| 343 | }, | ||
| 344 | }; | ||
| 345 | |||
| 346 | module_platform_driver(da9052_tsi_driver); | ||
| 347 | |||
| 348 | MODULE_DESCRIPTION("Touchscreen driver for Dialog Semiconductor DA9052"); | ||
| 349 | MODULE_AUTHOR("Anthony Olech <Anthony.Olech@diasemi.com>"); | ||
| 350 | MODULE_LICENSE("GPL"); | ||
| 351 | MODULE_ALIAS("platform:da9052-tsi"); | ||
diff --git a/drivers/input/touchscreen/dynapro.c b/drivers/input/touchscreen/dynapro.c index 1809677a651..455353908bd 100644 --- a/drivers/input/touchscreen/dynapro.c +++ b/drivers/input/touchscreen/dynapro.c | |||
| @@ -188,4 +188,19 @@ static struct serio_driver dynapro_drv = { | |||
| 188 | .disconnect = dynapro_disconnect, | 188 | .disconnect = dynapro_disconnect, |
| 189 | }; | 189 | }; |
| 190 | 190 | ||
| 191 | module_serio_driver(dynapro_drv); | 191 | /* |
| 192 | * The functions for inserting/removing us as a module. | ||
| 193 | */ | ||
| 194 | |||
| 195 | static int __init dynapro_init(void) | ||
| 196 | { | ||
| 197 | return serio_register_driver(&dynapro_drv); | ||
| 198 | } | ||
| 199 | |||
| 200 | static void __exit dynapro_exit(void) | ||
| 201 | { | ||
| 202 | serio_unregister_driver(&dynapro_drv); | ||
| 203 | } | ||
| 204 | |||
| 205 | module_init(dynapro_init); | ||
| 206 | module_exit(dynapro_exit); | ||
diff --git a/drivers/input/touchscreen/edt-ft5x06.c b/drivers/input/touchscreen/edt-ft5x06.c deleted file mode 100644 index a9170157b44..00000000000 --- a/drivers/input/touchscreen/edt-ft5x06.c +++ /dev/null | |||
| @@ -1,893 +0,0 @@ | |||
| 1 | /* | ||
| 2 | * Copyright (C) 2012 Simon Budig, <simon.budig@kernelconcepts.de> | ||
| 3 | * | ||
| 4 | * This software is licensed under the terms of the GNU General Public | ||
| 5 | * License version 2, as published by the Free Software Foundation, and | ||
| 6 | * may be copied, distributed, and modified under those terms. | ||
| 7 | * | ||
| 8 | * This program is distributed in the hope that it will be useful, | ||
| 9 | * but WITHOUT ANY WARRANTY; without even the implied warranty of | ||
| 10 | * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the | ||
| 11 | * GNU General Public License for more details. | ||
| 12 | * | ||
| 13 | * You should have received a copy of the GNU General Public | ||
| 14 | * License along with this library; if not, write to the Free Software | ||
| 15 | * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA | ||
| 16 | */ | ||
| 17 | |||
| 18 | /* | ||
| 19 | * This is a driver for the EDT "Polytouch" family of touch controllers | ||
| 20 | * based on the FocalTech FT5x06 line of chips. | ||
| 21 | * | ||
| 22 | * Development of this driver has been sponsored by Glyn: | ||
| 23 | * http://www.glyn.com/Products/Displays | ||
| 24 | */ | ||
| 25 | |||
| 26 | #include <linux/module.h> | ||
| 27 | #include <linux/ratelimit.h> | ||
| 28 | #include <linux/interrupt.h> | ||
| 29 | #include <linux/input.h> | ||
| 30 | #include <linux/i2c.h> | ||
| 31 | #include <linux/uaccess.h> | ||
| 32 | #include <linux/delay.h> | ||
| 33 | #include <linux/debugfs.h> | ||
| 34 | #include <linux/slab.h> | ||
| 35 | #include <linux/gpio.h> | ||
| 36 | #include <linux/input/mt.h> | ||
| 37 | #include <linux/input/edt-ft5x06.h> | ||
| 38 | |||
| 39 | #define MAX_SUPPORT_POINTS 5 | ||
| 40 | |||
| 41 | #define WORK_REGISTER_THRESHOLD 0x00 | ||
| 42 | #define WORK_REGISTER_REPORT_RATE 0x08 | ||
| 43 | #define WORK_REGISTER_GAIN 0x30 | ||
| 44 | #define WORK_REGISTER_OFFSET 0x31 | ||
| 45 | #define WORK_REGISTER_NUM_X 0x33 | ||
| 46 | #define WORK_REGISTER_NUM_Y 0x34 | ||
| 47 | |||
| 48 | #define WORK_REGISTER_OPMODE 0x3c | ||
| 49 | #define FACTORY_REGISTER_OPMODE 0x01 | ||
| 50 | |||
| 51 | #define TOUCH_EVENT_DOWN 0x00 | ||
| 52 | #define TOUCH_EVENT_UP 0x01 | ||
| 53 | #define TOUCH_EVENT_ON 0x02 | ||
| 54 | #define TOUCH_EVENT_RESERVED 0x03 | ||
| 55 | |||
| 56 | #define EDT_NAME_LEN 23 | ||
| 57 | #define EDT_SWITCH_MODE_RETRIES 10 | ||
| 58 | #define EDT_SWITCH_MODE_DELAY 5 /* msec */ | ||
| 59 | #define EDT_RAW_DATA_RETRIES 100 | ||
| 60 | #define EDT_RAW_DATA_DELAY 1 /* msec */ | ||
| 61 | |||
| 62 | struct edt_ft5x06_ts_data { | ||
| 63 | struct i2c_client *client; | ||
| 64 | struct input_dev *input; | ||
| 65 | u16 num_x; | ||
| 66 | u16 num_y; | ||
| 67 | |||
| 68 | #if defined(CONFIG_DEBUG_FS) | ||
| 69 | struct dentry *debug_dir; | ||
| 70 | u8 *raw_buffer; | ||
| 71 | size_t raw_bufsize; | ||
| 72 | #endif | ||
| 73 | |||
| 74 | struct mutex mutex; | ||
| 75 | bool factory_mode; | ||
| 76 | int threshold; | ||
| 77 | int gain; | ||
| 78 | int offset; | ||
| 79 | int report_rate; | ||
| 80 | |||
| 81 | char name[EDT_NAME_LEN]; | ||
| 82 | }; | ||
| 83 | |||
| 84 | static int edt_ft5x06_ts_readwrite(struct i2c_client *client, | ||
| 85 | u16 wr_len, u8 *wr_buf, | ||
| 86 | u16 rd_len, u8 *rd_buf) | ||
| 87 | { | ||
| 88 | struct i2c_msg wrmsg[2]; | ||
| 89 | int i = 0; | ||
| 90 | int ret; | ||
| 91 | |||
| 92 | if (wr_len) { | ||
| 93 | wrmsg[i].addr = client->addr; | ||
| 94 | wrmsg[i].flags = 0; | ||
| 95 | wrmsg[i].len = wr_len; | ||
| 96 | wrmsg[i].buf = wr_buf; | ||
| 97 | i++; | ||
| 98 | } | ||
| 99 | if (rd_len) { | ||
| 100 | wrmsg[i].addr = client->addr; | ||
| 101 | wrmsg[i].flags = I2C_M_RD; | ||
| 102 | wrmsg[i].len = rd_len; | ||
| 103 | wrmsg[i].buf = rd_buf; | ||
| 104 | i++; | ||
| 105 | } | ||
| 106 | |||
| 107 | ret = i2c_transfer(client->adapter, wrmsg, i); | ||
| 108 | if (ret < 0) | ||
| 109 | return ret; | ||
| 110 | if (ret != i) | ||
| 111 | return -EIO; | ||
| 112 | |||
| 113 | return 0; | ||
| 114 | } | ||
| 115 | |||
| 116 | static bool edt_ft5x06_ts_check_crc(struct edt_ft5x06_ts_data *tsdata, | ||
| 117 | u8 *buf, int buflen) | ||
| 118 | { | ||
| 119 | int i; | ||
| 120 | u8 crc = 0; | ||
| 121 | |||
| 122 | for (i = 0; i < buflen - 1; i++) | ||
| 123 | crc ^= buf[i]; | ||
| 124 | |||
| 125 | if (crc != buf[buflen-1]) { | ||
| 126 | dev_err_ratelimited(&tsdata->client->dev, | ||
| 127 | "crc error: 0x%02x expected, got 0x%02x\n", | ||
| 128 | crc, buf[buflen-1]); | ||
| 129 | return false; | ||
| 130 | } | ||
| 131 | |||
| 132 | return true; | ||
| 133 | } | ||
| 134 | |||
| 135 | static irqreturn_t edt_ft5x06_ts_isr(int irq, void *dev_id) | ||
| 136 | { | ||
| 137 | struct edt_ft5x06_ts_data *tsdata = dev_id; | ||
| 138 | struct device *dev = &tsdata->client->dev; | ||
| 139 | u8 cmd = 0xf9; | ||
| 140 | u8 rdbuf[26]; | ||
| 141 | int i, type, x, y, id; | ||
| 142 | int error; | ||
| 143 | |||
| 144 | memset(rdbuf, 0, sizeof(rdbuf)); | ||
| 145 | |||
| 146 | error = edt_ft5x06_ts_readwrite(tsdata->client, | ||
| 147 | sizeof(cmd), &cmd, | ||
| 148 | sizeof(rdbuf), rdbuf); | ||
| 149 | if (error) { | ||
| 150 | dev_err_ratelimited(dev, "Unable to fetch data, error: %d\n", | ||
| 151 | error); | ||
| 152 | goto out; | ||
| 153 | } | ||
| 154 | |||
| 155 | if (rdbuf[0] != 0xaa || rdbuf[1] != 0xaa || rdbuf[2] != 26) { | ||
| 156 | dev_err_ratelimited(dev, "Unexpected header: %02x%02x%02x!\n", | ||
| 157 | rdbuf[0], rdbuf[1], rdbuf[2]); | ||
| 158 | goto out; | ||
| 159 | } | ||
| 160 | |||
| 161 | if (!edt_ft5x06_ts_check_crc(tsdata, rdbuf, 26)) | ||
| 162 | goto out; | ||
| 163 | |||
| 164 | for (i = 0; i < MAX_SUPPORT_POINTS; i++) { | ||
| 165 | u8 *buf = &rdbuf[i * 4 + 5]; | ||
| 166 | bool down; | ||
| 167 | |||
| 168 | type = buf[0] >> 6; | ||
| 169 | /* ignore Reserved events */ | ||
| 170 | if (type == TOUCH_EVENT_RESERVED) | ||
| 171 | continue; | ||
| 172 | |||
| 173 | x = ((buf[0] << 8) | buf[1]) & 0x0fff; | ||
| 174 | y = ((buf[2] << 8) | buf[3]) & 0x0fff; | ||
| 175 | id = (buf[2] >> 4) & 0x0f; | ||
| 176 | down = (type != TOUCH_EVENT_UP); | ||
| 177 | |||
| 178 | input_mt_slot(tsdata->input, id); | ||
| 179 | input_mt_report_slot_state(tsdata->input, MT_TOOL_FINGER, down); | ||
| 180 | |||
| 181 | if (!down) | ||
| 182 | continue; | ||
| 183 | |||
| 184 | input_report_abs(tsdata->input, ABS_MT_POSITION_X, x); | ||
| 185 | input_report_abs(tsdata->input, ABS_MT_POSITION_Y, y); | ||
| 186 | } | ||
| 187 | |||
| 188 | input_mt_report_pointer_emulation(tsdata->input, true); | ||
| 189 | input_sync(tsdata->input); | ||
| 190 | |||
| 191 | out: | ||
| 192 | return IRQ_HANDLED; | ||
| 193 | } | ||
| 194 | |||
| 195 | static int edt_ft5x06_register_write(struct edt_ft5x06_ts_data *tsdata, | ||
| 196 | u8 addr, u8 value) | ||
| 197 | { | ||
| 198 | u8 wrbuf[4]; | ||
| 199 | |||
| 200 | wrbuf[0] = tsdata->factory_mode ? 0xf3 : 0xfc; | ||
| 201 | wrbuf[1] = tsdata->factory_mode ? addr & 0x7f : addr & 0x3f; | ||
| 202 | wrbuf[2] = value; | ||
| 203 | wrbuf[3] = wrbuf[0] ^ wrbuf[1] ^ wrbuf[2]; | ||
| 204 | |||
| 205 | return edt_ft5x06_ts_readwrite(tsdata->client, 4, wrbuf, 0, NULL); | ||
| 206 | } | ||
| 207 | |||
| 208 | static int edt_ft5x06_register_read(struct edt_ft5x06_ts_data *tsdata, | ||
| 209 | u8 addr) | ||
| 210 | { | ||
| 211 | u8 wrbuf[2], rdbuf[2]; | ||
| 212 | int error; | ||
| 213 | |||
| 214 | wrbuf[0] = tsdata->factory_mode ? 0xf3 : 0xfc; | ||
| 215 | wrbuf[1] = tsdata->factory_mode ? addr & 0x7f : addr & 0x3f; | ||
| 216 | wrbuf[1] |= tsdata->factory_mode ? 0x80 : 0x40; | ||
| 217 | |||
| 218 | error = edt_ft5x06_ts_readwrite(tsdata->client, 2, wrbuf, 2, rdbuf); | ||
| 219 | if (error) | ||
| 220 | return error; | ||
| 221 | |||
| 222 | if ((wrbuf[0] ^ wrbuf[1] ^ rdbuf[0]) != rdbuf[1]) { | ||
| 223 | dev_err(&tsdata->client->dev, | ||
| 224 | "crc error: 0x%02x expected, got 0x%02x\n", | ||
| 225 | wrbuf[0] ^ wrbuf[1] ^ rdbuf[0], rdbuf[1]); | ||
| 226 | return -EIO; | ||
| 227 | } | ||
| 228 | |||
| 229 | return rdbuf[0]; | ||
| 230 | } | ||
| 231 | |||
| 232 | struct edt_ft5x06_attribute { | ||
| 233 | struct device_attribute dattr; | ||
| 234 | size_t field_offset; | ||
| 235 | u8 limit_low; | ||
| 236 | u8 limit_high; | ||
| 237 | u8 addr; | ||
| 238 | }; | ||
| 239 | |||
| 240 | #define EDT_ATTR(_field, _mode, _addr, _limit_low, _limit_high) \ | ||
| 241 | struct edt_ft5x06_attribute edt_ft5x06_attr_##_field = { \ | ||
| 242 | .dattr = __ATTR(_field, _mode, \ | ||
| 243 | edt_ft5x06_setting_show, \ | ||
| 244 | edt_ft5x06_setting_store), \ | ||
| 245 | .field_offset = \ | ||
| 246 | offsetof(struct edt_ft5x06_ts_data, _field), \ | ||
| 247 | .limit_low = _limit_low, \ | ||
| 248 | .limit_high = _limit_high, \ | ||
| 249 | .addr = _addr, \ | ||
| 250 | } | ||
| 251 | |||
| 252 | static ssize_t edt_ft5x06_setting_show(struct device *dev, | ||
| 253 | struct device_attribute *dattr, | ||
| 254 | char *buf) | ||
| 255 | { | ||
| 256 | struct i2c_client *client = to_i2c_client(dev); | ||
| 257 | struct edt_ft5x06_ts_data *tsdata = i2c_get_clientdata(client); | ||
| 258 | struct edt_ft5x06_attribute *attr = | ||
| 259 | container_of(dattr, struct edt_ft5x06_attribute, dattr); | ||
| 260 | u8 *field = (u8 *)((char *)tsdata + attr->field_offset); | ||
| 261 | int val; | ||
| 262 | size_t count = 0; | ||
| 263 | int error = 0; | ||
| 264 | |||
| 265 | mutex_lock(&tsdata->mutex); | ||
| 266 | |||
| 267 | if (tsdata->factory_mode) { | ||
| 268 | error = -EIO; | ||
| 269 | goto out; | ||
| 270 | } | ||
| 271 | |||
| 272 | val = edt_ft5x06_register_read(tsdata, attr->addr); | ||
| 273 | if (val < 0) { | ||
| 274 | error = val; | ||
| 275 | dev_err(&tsdata->client->dev, | ||
| 276 | "Failed to fetch attribute %s, error %d\n", | ||
| 277 | dattr->attr.name, error); | ||
| 278 | goto out; | ||
| 279 | } | ||
| 280 | |||
| 281 | if (val != *field) { | ||
| 282 | dev_warn(&tsdata->client->dev, | ||
| 283 | "%s: read (%d) and stored value (%d) differ\n", | ||
| 284 | dattr->attr.name, val, *field); | ||
| 285 | *field = val; | ||
| 286 | } | ||
| 287 | |||
| 288 | count = scnprintf(buf, PAGE_SIZE, "%d\n", val); | ||
| 289 | out: | ||
| 290 | mutex_unlock(&tsdata->mutex); | ||
| 291 | return error ?: count; | ||
| 292 | } | ||
| 293 | |||
| 294 | static ssize_t edt_ft5x06_setting_store(struct device *dev, | ||
| 295 | struct device_attribute *dattr, | ||
| 296 | const char *buf, size_t count) | ||
| 297 | { | ||
| 298 | struct i2c_client *client = to_i2c_client(dev); | ||
| 299 | struct edt_ft5x06_ts_data *tsdata = i2c_get_clientdata(client); | ||
| 300 | struct edt_ft5x06_attribute *attr = | ||
| 301 | container_of(dattr, struct edt_ft5x06_attribute, dattr); | ||
| 302 | u8 *field = (u8 *)((char *)tsdata + attr->field_offset); | ||
| 303 | unsigned int val; | ||
| 304 | int error; | ||
| 305 | |||
| 306 | mutex_lock(&tsdata->mutex); | ||
| 307 | |||
| 308 | if (tsdata->factory_mode) { | ||
| 309 | error = -EIO; | ||
| 310 | goto out; | ||
| 311 | } | ||
| 312 | |||
| 313 | error = kstrtouint(buf, 0, &val); | ||
| 314 | if (error) | ||
| 315 | goto out; | ||
| 316 | |||
| 317 | if (val < attr->limit_low || val > attr->limit_high) { | ||
| 318 | error = -ERANGE; | ||
| 319 | goto out; | ||
| 320 | } | ||
| 321 | |||
| 322 | error = edt_ft5x06_register_write(tsdata, attr->addr, val); | ||
| 323 | if (error) { | ||
| 324 | dev_err(&tsdata->client->dev, | ||
| 325 | "Failed to update attribute %s, error: %d\n", | ||
| 326 | dattr->attr.name, error); | ||
| 327 | goto out; | ||
| 328 | } | ||
| 329 | |||
| 330 | *field = val; | ||
| 331 | |||
| 332 | out: | ||
| 333 | mutex_unlock(&tsdata->mutex); | ||
| 334 | return error ?: count; | ||
| 335 | } | ||
| 336 | |||
| 337 | static EDT_ATTR(gain, S_IWUSR | S_IRUGO, WORK_REGISTER_GAIN, 0, 31); | ||
| 338 | static EDT_ATTR(offset, S_IWUSR | S_IRUGO, WORK_REGISTER_OFFSET, 0, 31); | ||
| 339 | static EDT_ATTR(threshold, S_IWUSR | S_IRUGO, | ||
| 340 | WORK_REGISTER_THRESHOLD, 20, 80); | ||
| 341 | static EDT_ATTR(report_rate, S_IWUSR | S_IRUGO, | ||
| 342 | WORK_REGISTER_REPORT_RATE, 3, 14); | ||
| 343 | |||
| 344 | static struct attribute *edt_ft5x06_attrs[] = { | ||
| 345 | &edt_ft5x06_attr_gain.dattr.attr, | ||
| 346 | &edt_ft5x06_attr_offset.dattr.attr, | ||
| 347 | &edt_ft5x06_attr_threshold.dattr.attr, | ||
| 348 | &edt_ft5x06_attr_report_rate.dattr.attr, | ||
| 349 | NULL | ||
| 350 | }; | ||
| 351 | |||
| 352 | static const struct attribute_group edt_ft5x06_attr_group = { | ||
| 353 | .attrs = edt_ft5x06_attrs, | ||
| 354 | }; | ||
| 355 | |||
| 356 | #ifdef CONFIG_DEBUG_FS | ||
| 357 | static int edt_ft5x06_factory_mode(struct edt_ft5x06_ts_data *tsdata) | ||
| 358 | { | ||
| 359 | struct i2c_client *client = tsdata->client; | ||
| 360 | int retries = EDT_SWITCH_MODE_RETRIES; | ||
| 361 | int ret; | ||
| 362 | int error; | ||
| 363 | |||
| 364 | disable_irq(client->irq); | ||
| 365 | |||
| 366 | if (!tsdata->raw_buffer) { | ||
| 367 | tsdata->raw_bufsize = tsdata->num_x * tsdata->num_y * | ||
| 368 | sizeof(u16); | ||
| 369 | tsdata->raw_buffer = kzalloc(tsdata->raw_bufsize, GFP_KERNEL); | ||
| 370 | if (!tsdata->raw_buffer) { | ||
| 371 | error = -ENOMEM; | ||
| 372 | goto err_out; | ||
| 373 | } | ||
| 374 | } | ||
| 375 | |||
| 376 | /* mode register is 0x3c when in the work mode */ | ||
| 377 | error = edt_ft5x06_register_write(tsdata, WORK_REGISTER_OPMODE, 0x03); | ||
| 378 | if (error) { | ||
| 379 | dev_err(&client->dev, | ||
| 380 | "failed to switch to factory mode, error %d\n", error); | ||
| 381 | goto err_out; | ||
| 382 | } | ||
| 383 | |||
| 384 | tsdata->factory_mode = true; | ||
| 385 | do { | ||
| 386 | mdelay(EDT_SWITCH_MODE_DELAY); | ||
| 387 | /* mode register is 0x01 when in factory mode */ | ||
| 388 | ret = edt_ft5x06_register_read(tsdata, FACTORY_REGISTER_OPMODE); | ||
| 389 | if (ret == 0x03) | ||
| 390 | break; | ||
| 391 | } while (--retries > 0); | ||
| 392 | |||
| 393 | if (retries == 0) { | ||
| 394 | dev_err(&client->dev, "not in factory mode after %dms.\n", | ||
| 395 | EDT_SWITCH_MODE_RETRIES * EDT_SWITCH_MODE_DELAY); | ||
| 396 | error = -EIO; | ||
| 397 | goto err_out; | ||
| 398 | } | ||
| 399 | |||
| 400 | return 0; | ||
| 401 | |||
| 402 | err_out: | ||
| 403 | kfree(tsdata->raw_buffer); | ||
| 404 | tsdata->raw_buffer = NULL; | ||
| 405 | tsdata->factory_mode = false; | ||
| 406 | enable_irq(client->irq); | ||
| 407 | |||
| 408 | return error; | ||
| 409 | } | ||
| 410 | |||
| 411 | static int edt_ft5x06_work_mode(struct edt_ft5x06_ts_data *tsdata) | ||
| 412 | { | ||
| 413 | struct i2c_client *client = tsdata->client; | ||
| 414 | int retries = EDT_SWITCH_MODE_RETRIES; | ||
| 415 | int ret; | ||
| 416 | int error; | ||
| 417 | |||
| 418 | /* mode register is 0x01 when in the factory mode */ | ||
| 419 | error = edt_ft5x06_register_write(tsdata, FACTORY_REGISTER_OPMODE, 0x1); | ||
| 420 | if (error) { | ||
| 421 | dev_err(&client->dev, | ||
| 422 | "failed to switch to work mode, error: %d\n", error); | ||
| 423 | return error; | ||
| 424 | } | ||
| 425 | |||
| 426 | tsdata->factory_mode = false; | ||
| 427 | |||
| 428 | do { | ||
| 429 | mdelay(EDT_SWITCH_MODE_DELAY); | ||
| 430 | /* mode register is 0x01 when in factory mode */ | ||
| 431 | ret = edt_ft5x06_register_read(tsdata, WORK_REGISTER_OPMODE); | ||
| 432 | if (ret == 0x01) | ||
| 433 | break; | ||
| 434 | } while (--retries > 0); | ||
| 435 | |||
| 436 | if (retries == 0) { | ||
| 437 | dev_err(&client->dev, "not in work mode after %dms.\n", | ||
| 438 | EDT_SWITCH_MODE_RETRIES * EDT_SWITCH_MODE_DELAY); | ||
| 439 | tsdata->factory_mode = true; | ||
| 440 | return -EIO; | ||
| 441 | } | ||
| 442 | |||
| 443 | if (tsdata->raw_buffer) | ||
| 444 | kfree(tsdata->raw_buffer); | ||
| 445 | tsdata->raw_buffer = NULL; | ||
| 446 | |||
| 447 | /* restore parameters */ | ||
| 448 | edt_ft5x06_register_write(tsdata, WORK_REGISTER_THRESHOLD, | ||
| 449 | tsdata->threshold); | ||
| 450 | edt_ft5x06_register_write(tsdata, WORK_REGISTER_GAIN, | ||
| 451 | tsdata->gain); | ||
| 452 | edt_ft5x06_register_write(tsdata, WORK_REGISTER_OFFSET, | ||
| 453 | tsdata->offset); | ||
| 454 | edt_ft5x06_register_write(tsdata, WORK_REGISTER_REPORT_RATE, | ||
| 455 | tsdata->report_rate); | ||
| 456 | |||
| 457 | enable_irq(client->irq); | ||
| 458 | |||
| 459 | return 0; | ||
| 460 | } | ||
| 461 | |||
| 462 | static int edt_ft5x06_debugfs_mode_get(void *data, u64 *mode) | ||
| 463 | { | ||
| 464 | struct edt_ft5x06_ts_data *tsdata = data; | ||
| 465 | |||
| 466 | *mode = tsdata->factory_mode; | ||
| 467 | |||
| 468 | return 0; | ||
| 469 | }; | ||
| 470 | |||
| 471 | static int edt_ft5x06_debugfs_mode_set(void *data, u64 mode) | ||
| 472 | { | ||
| 473 | struct edt_ft5x06_ts_data *tsdata = data; | ||
| 474 | int retval = 0; | ||
| 475 | |||
| 476 | if (mode > 1) | ||
| 477 | return -ERANGE; | ||
| 478 | |||
| 479 | mutex_lock(&tsdata->mutex); | ||
| 480 | |||
| 481 | if (mode != tsdata->factory_mode) { | ||
| 482 | retval = mode ? edt_ft5x06_factory_mode(tsdata) : | ||
| 483 | edt_ft5x06_work_mode(tsdata); | ||
| 484 | } | ||
| 485 | |||
| 486 | mutex_unlock(&tsdata->mutex); | ||
| 487 | |||
| 488 | return retval; | ||
| 489 | }; | ||
| 490 | |||
| 491 | DEFINE_SIMPLE_ATTRIBUTE(debugfs_mode_fops, edt_ft5x06_debugfs_mode_get, | ||
| 492 | edt_ft5x06_debugfs_mode_set, "%llu\n"); | ||
| 493 | |||
| 494 | static ssize_t edt_ft5x06_debugfs_raw_data_read(struct file *file, | ||
| 495 | char __user *buf, size_t count, loff_t *off) | ||
| 496 | { | ||
| 497 | struct edt_ft5x06_ts_data *tsdata = file->private_data; | ||
| 498 | struct i2c_client *client = tsdata->client; | ||
| 499 | int retries = EDT_RAW_DATA_RETRIES; | ||
| 500 | int val, i, error; | ||
| 501 | size_t read = 0; | ||
| 502 | int colbytes; | ||
| 503 | char wrbuf[3]; | ||
| 504 | u8 *rdbuf; | ||
| 505 | |||
| 506 | if (*off < 0 || *off >= tsdata->raw_bufsize) | ||
| 507 | return 0; | ||
| 508 | |||
| 509 | mutex_lock(&tsdata->mutex); | ||
| 510 | |||
| 511 | if (!tsdata->factory_mode || !tsdata->raw_buffer) { | ||
| 512 | error = -EIO; | ||
| 513 | goto out; | ||
| 514 | } | ||
| 515 | |||
| 516 | error = edt_ft5x06_register_write(tsdata, 0x08, 0x01); | ||
| 517 | if (error) { | ||
| 518 | dev_dbg(&client->dev, | ||
| 519 | "failed to write 0x08 register, error %d\n", error); | ||
| 520 | goto out; | ||
| 521 | } | ||
| 522 | |||
| 523 | do { | ||
| 524 | msleep(EDT_RAW_DATA_DELAY); | ||
| 525 | val = edt_ft5x06_register_read(tsdata, 0x08); | ||
| 526 | if (val < 1) | ||
| 527 | break; | ||
| 528 | } while (--retries > 0); | ||
| 529 | |||
| 530 | if (val < 0) { | ||
| 531 | error = val; | ||
| 532 | dev_dbg(&client->dev, | ||
| 533 | "failed to read 0x08 register, error %d\n", error); | ||
| 534 | goto out; | ||
| 535 | } | ||
| 536 | |||
| 537 | if (retries == 0) { | ||
| 538 | dev_dbg(&client->dev, | ||
| 539 | "timed out waiting for register to settle\n"); | ||
| 540 | error = -ETIMEDOUT; | ||
| 541 | goto out; | ||
| 542 | } | ||
| 543 | |||
| 544 | rdbuf = tsdata->raw_buffer; | ||
| 545 | colbytes = tsdata->num_y * sizeof(u16); | ||
| 546 | |||
| 547 | wrbuf[0] = 0xf5; | ||
| 548 | wrbuf[1] = 0x0e; | ||
| 549 | for (i = 0; i < tsdata->num_x; i++) { | ||
| 550 | wrbuf[2] = i; /* column index */ | ||
| 551 | error = edt_ft5x06_ts_readwrite(tsdata->client, | ||
| 552 | sizeof(wrbuf), wrbuf, | ||
| 553 | colbytes, rdbuf); | ||
| 554 | if (error) | ||
| 555 | goto out; | ||
| 556 | |||
| 557 | rdbuf += colbytes; | ||
| 558 | } | ||
| 559 | |||
| 560 | read = min_t(size_t, count, tsdata->raw_bufsize - *off); | ||
| 561 | if (copy_to_user(buf, tsdata->raw_buffer + *off, read)) { | ||
| 562 | error = -EFAULT; | ||
| 563 | goto out; | ||
| 564 | } | ||
| 565 | |||
| 566 | *off += read; | ||
| 567 | out: | ||
| 568 | mutex_unlock(&tsdata->mutex); | ||
| 569 | return error ?: read; | ||
| 570 | }; | ||
| 571 | |||
| 572 | |||
| 573 | static const struct file_operations debugfs_raw_data_fops = { | ||
| 574 | .open = simple_open, | ||
| 575 | .read = edt_ft5x06_debugfs_raw_data_read, | ||
| 576 | }; | ||
| 577 | |||
| 578 | static void | ||
| 579 | edt_ft5x06_ts_prepare_debugfs(struct edt_ft5x06_ts_data *tsdata, | ||
| 580 | const char *debugfs_name) | ||
| 581 | { | ||
| 582 | tsdata->debug_dir = debugfs_create_dir(debugfs_name, NULL); | ||
| 583 | if (!tsdata->debug_dir) | ||
| 584 | return; | ||
| 585 | |||
| 586 | debugfs_create_u16("num_x", S_IRUSR, tsdata->debug_dir, &tsdata->num_x); | ||
| 587 | debugfs_create_u16("num_y", S_IRUSR, tsdata->debug_dir, &tsdata->num_y); | ||
| 588 | |||
| 589 | debugfs_create_file("mode", S_IRUSR | S_IWUSR, | ||
| 590 | tsdata->debug_dir, tsdata, &debugfs_mode_fops); | ||
| 591 | debugfs_create_file("raw_data", S_IRUSR, | ||
| 592 | tsdata->debug_dir, tsdata, &debugfs_raw_data_fops); | ||
| 593 | } | ||
| 594 | |||
| 595 | static void | ||
| 596 | edt_ft5x06_ts_teardown_debugfs(struct edt_ft5x06_ts_data *tsdata) | ||
| 597 | { | ||
| 598 | if (tsdata->debug_dir) | ||
| 599 | debugfs_remove_recursive(tsdata->debug_dir); | ||
| 600 | kfree(tsdata->raw_buffer); | ||
| 601 | } | ||
| 602 | |||
| 603 | #else | ||
| 604 | |||
| 605 | static inline void | ||
| 606 | edt_ft5x06_ts_prepare_debugfs(struct edt_ft5x06_ts_data *tsdata, | ||
| 607 | const char *debugfs_name) | ||
| 608 | { | ||
| 609 | } | ||
| 610 | |||
| 611 | static inline void | ||
| 612 | edt_ft5x06_ts_teardown_debugfs(struct edt_ft5x06_ts_data *tsdata) | ||
| 613 | { | ||
| 614 | } | ||
| 615 | |||
| 616 | #endif /* CONFIG_DEBUGFS */ | ||
| 617 | |||
| 618 | |||
| 619 | |||
| 620 | static int edt_ft5x06_ts_reset(struct i2c_client *client, | ||
| 621 | int reset_pin) | ||
| 622 | { | ||
| 623 | int error; | ||
| 624 | |||
| 625 | if (gpio_is_valid(reset_pin)) { | ||
| 626 | /* this pulls reset down, enabling the low active reset */ | ||
| 627 | error = gpio_request_one(reset_pin, GPIOF_OUT_INIT_LOW, | ||
| 628 | "edt-ft5x06 reset"); | ||
| 629 | if (error) { | ||
| 630 | dev_err(&client->dev, | ||
| 631 | "Failed to request GPIO %d as reset pin, error %d\n", | ||
| 632 | reset_pin, error); | ||
| 633 | return error; | ||
| 634 | } | ||
| 635 | |||
| 636 | mdelay(50); | ||
| 637 | gpio_set_value(reset_pin, 1); | ||
| 638 | mdelay(100); | ||
| 639 | } | ||
| 640 | |||
| 641 | return 0; | ||
| 642 | } | ||
| 643 | |||
| 644 | static int edt_ft5x06_ts_identify(struct i2c_client *client, | ||
| 645 | char *model_name, | ||
| 646 | char *fw_version) | ||
| 647 | { | ||
| 648 | u8 rdbuf[EDT_NAME_LEN]; | ||
| 649 | char *p; | ||
| 650 | int error; | ||
| 651 | |||
| 652 | error = edt_ft5x06_ts_readwrite(client, 1, "\xbb", | ||
| 653 | EDT_NAME_LEN - 1, rdbuf); | ||
| 654 | if (error) | ||
| 655 | return error; | ||
| 656 | |||
| 657 | /* remove last '$' end marker */ | ||
| 658 | rdbuf[EDT_NAME_LEN - 1] = '\0'; | ||
| 659 | if (rdbuf[EDT_NAME_LEN - 2] == '$') | ||
| 660 | rdbuf[EDT_NAME_LEN - 2] = '\0'; | ||
| 661 | |||
| 662 | /* look for Model/Version separator */ | ||
| 663 | p = strchr(rdbuf, '*'); | ||
| 664 | if (p) | ||
| 665 | *p++ = '\0'; | ||
| 666 | |||
| 667 | strlcpy(model_name, rdbuf + 1, EDT_NAME_LEN); | ||
| 668 | strlcpy(fw_version, p ? p : "", EDT_NAME_LEN); | ||
| 669 | |||
| 670 | return 0; | ||
| 671 | } | ||
| 672 | |||
| 673 | #define EDT_ATTR_CHECKSET(name, reg) \ | ||
| 674 | if (pdata->name >= edt_ft5x06_attr_##name.limit_low && \ | ||
| 675 | pdata->name <= edt_ft5x06_attr_##name.limit_high) \ | ||
| 676 | edt_ft5x06_register_write(tsdata, reg, pdata->name) | ||
| 677 | |||
| 678 | static void | ||
| 679 | edt_ft5x06_ts_get_defaults(struct edt_ft5x06_ts_data *tsdata, | ||
| 680 | const struct edt_ft5x06_platform_data *pdata) | ||
| 681 | { | ||
| 682 | if (!pdata->use_parameters) | ||
| 683 | return; | ||
| 684 | |||
| 685 | /* pick up defaults from the platform data */ | ||
| 686 | EDT_ATTR_CHECKSET(threshold, WORK_REGISTER_THRESHOLD); | ||
| 687 | EDT_ATTR_CHECKSET(gain, WORK_REGISTER_GAIN); | ||
| 688 | EDT_ATTR_CHECKSET(offset, WORK_REGISTER_OFFSET); | ||
| 689 | EDT_ATTR_CHECKSET(report_rate, WORK_REGISTER_REPORT_RATE); | ||
| 690 | } | ||
| 691 | |||
| 692 | static void | ||
| 693 | edt_ft5x06_ts_get_parameters(struct edt_ft5x06_ts_data *tsdata) | ||
| 694 | { | ||
| 695 | tsdata->threshold = edt_ft5x06_register_read(tsdata, | ||
| 696 | WORK_REGISTER_THRESHOLD); | ||
| 697 | tsdata->gain = edt_ft5x06_register_read(tsdata, WORK_REGISTER_GAIN); | ||
| 698 | tsdata->offset = edt_ft5x06_register_read(tsdata, WORK_REGISTER_OFFSET); | ||
| 699 | tsdata->report_rate = edt_ft5x06_register_read(tsdata, | ||
| 700 | WORK_REGISTER_REPORT_RATE); | ||
| 701 | tsdata->num_x = edt_ft5x06_register_read(tsdata, WORK_REGISTER_NUM_X); | ||
| 702 | tsdata->num_y = edt_ft5x06_register_read(tsdata, WORK_REGISTER_NUM_Y); | ||
| 703 | } | ||
| 704 | |||
| 705 | static int edt_ft5x06_ts_probe(struct i2c_client *client, | ||
| 706 | const struct i2c_device_id *id) | ||
| 707 | { | ||
| 708 | const struct edt_ft5x06_platform_data *pdata = | ||
| 709 | client->dev.platform_data; | ||
| 710 | struct edt_ft5x06_ts_data *tsdata; | ||
| 711 | struct input_dev *input; | ||
| 712 | int error; | ||
| 713 | char fw_version[EDT_NAME_LEN]; | ||
| 714 | |||
| 715 | dev_dbg(&client->dev, "probing for EDT FT5x06 I2C\n"); | ||
| 716 | |||
| 717 | if (!pdata) { | ||
| 718 | dev_err(&client->dev, "no platform data?\n"); | ||
| 719 | return -EINVAL; | ||
| 720 | } | ||
| 721 | |||
| 722 | error = edt_ft5x06_ts_reset(client, pdata->reset_pin); | ||
| 723 | if (error) | ||
| 724 | return error; | ||
| 725 | |||
| 726 | if (gpio_is_valid(pdata->irq_pin)) { | ||
| 727 | error = gpio_request_one(pdata->irq_pin, | ||
| 728 | GPIOF_IN, "edt-ft5x06 irq"); | ||
| 729 | if (error) { | ||
| 730 | dev_err(&client->dev, | ||
| 731 | "Failed to request GPIO %d, error %d\n", | ||
| 732 | pdata->irq_pin, error); | ||
| 733 | return error; | ||
| 734 | } | ||
| 735 | } | ||
| 736 | |||
| 737 | tsdata = kzalloc(sizeof(*tsdata), GFP_KERNEL); | ||
| 738 | input = input_allocate_device(); | ||
| 739 | if (!tsdata || !input) { | ||
| 740 | dev_err(&client->dev, "failed to allocate driver data.\n"); | ||
| 741 | error = -ENOMEM; | ||
| 742 | goto err_free_mem; | ||
| 743 | } | ||
| 744 | |||
| 745 | mutex_init(&tsdata->mutex); | ||
| 746 | tsdata->client = client; | ||
| 747 | tsdata->input = input; | ||
| 748 | tsdata->factory_mode = false; | ||
| 749 | |||
| 750 | error = edt_ft5x06_ts_identify(client, tsdata->name, fw_version); | ||
| 751 | if (error) { | ||
| 752 | dev_err(&client->dev, "touchscreen probe failed\n"); | ||
| 753 | goto err_free_mem; | ||
| 754 | } | ||
| 755 | |||
| 756 | edt_ft5x06_ts_get_defaults(tsdata, pdata); | ||
| 757 | edt_ft5x06_ts_get_parameters(tsdata); | ||
| 758 | |||
| 759 | dev_dbg(&client->dev, | ||
| 760 | "Model \"%s\", Rev. \"%s\", %dx%d sensors\n", | ||
| 761 | tsdata->name, fw_version, tsdata->num_x, tsdata->num_y); | ||
| 762 | |||
| 763 | input->name = tsdata->name; | ||
| 764 | input->id.bustype = BUS_I2C; | ||
| 765 | input->dev.parent = &client->dev; | ||
| 766 | |||
| 767 | __set_bit(EV_SYN, input->evbit); | ||
| 768 | __set_bit(EV_KEY, input->evbit); | ||
| 769 | __set_bit(EV_ABS, input->evbit); | ||
| 770 | __set_bit(BTN_TOUCH, input->keybit); | ||
| 771 | input_set_abs_params(input, ABS_X, 0, tsdata->num_x * 64 - 1, 0, 0); | ||
| 772 | input_set_abs_params(input, ABS_Y, 0, tsdata->num_y * 64 - 1, 0, 0); | ||
| 773 | input_set_abs_params(input, ABS_MT_POSITION_X, | ||
| 774 | 0, tsdata->num_x * 64 - 1, 0, 0); | ||
| 775 | input_set_abs_params(input, ABS_MT_POSITION_Y, | ||
| 776 | 0, tsdata->num_y * 64 - 1, 0, 0); | ||
| 777 | error = input_mt_init_slots(input, MAX_SUPPORT_POINTS, 0); | ||
| 778 | if (error) { | ||
| 779 | dev_err(&client->dev, "Unable to init MT slots.\n"); | ||
| 780 | goto err_free_mem; | ||
| 781 | } | ||
| 782 | |||
| 783 | input_set_drvdata(input, tsdata); | ||
| 784 | i2c_set_clientdata(client, tsdata); | ||
| 785 | |||
| 786 | error = request_threaded_irq(client->irq, NULL, edt_ft5x06_ts_isr, | ||
| 787 | IRQF_TRIGGER_FALLING | IRQF_ONESHOT, | ||
| 788 | client->name, tsdata); | ||
| 789 | if (error) { | ||
| 790 | dev_err(&client->dev, "Unable to request touchscreen IRQ.\n"); | ||
| 791 | goto err_free_mem; | ||
| 792 | } | ||
| 793 | |||
| 794 | error = sysfs_create_group(&client->dev.kobj, &edt_ft5x06_attr_group); | ||
| 795 | if (error) | ||
| 796 | goto err_free_irq; | ||
| 797 | |||
| 798 | error = input_register_device(input); | ||
| 799 | if (error) | ||
| 800 | goto err_remove_attrs; | ||
| 801 | |||
| 802 | edt_ft5x06_ts_prepare_debugfs(tsdata, dev_driver_string(&client->dev)); | ||
| 803 | device_init_wakeup(&client->dev, 1); | ||
| 804 | |||
| 805 | dev_dbg(&client->dev, | ||
| 806 | "EDT FT5x06 initialized: IRQ pin %d, Reset pin %d.\n", | ||
| 807 | pdata->irq_pin, pdata->reset_pin); | ||
| 808 | |||
| 809 | return 0; | ||
| 810 | |||
| 811 | err_remove_attrs: | ||
| 812 | sysfs_remove_group(&client->dev.kobj, &edt_ft5x06_attr_group); | ||
| 813 | err_free_irq: | ||
| 814 | free_irq(client->irq, tsdata); | ||
| 815 | err_free_mem: | ||
| 816 | input_free_device(input); | ||
| 817 | kfree(tsdata); | ||
| 818 | |||
| 819 | if (gpio_is_valid(pdata->irq_pin)) | ||
| 820 | gpio_free(pdata->irq_pin); | ||
| 821 | |||
| 822 | return error; | ||
| 823 | } | ||
| 824 | |||
| 825 | static int edt_ft5x06_ts_remove(struct i2c_client *client) | ||
| 826 | { | ||
| 827 | const struct edt_ft5x06_platform_data *pdata = | ||
| 828 | dev_get_platdata(&client->dev); | ||
| 829 | struct edt_ft5x06_ts_data *tsdata = i2c_get_clientdata(client); | ||
| 830 | |||
| 831 | edt_ft5x06_ts_teardown_debugfs(tsdata); | ||
| 832 | sysfs_remove_group(&client->dev.kobj, &edt_ft5x06_attr_group); | ||
| 833 | |||
| 834 | free_irq(client->irq, tsdata); | ||
| 835 | input_unregister_device(tsdata->input); | ||
| 836 | |||
| 837 | if (gpio_is_valid(pdata->irq_pin)) | ||
| 838 | gpio_free(pdata->irq_pin); | ||
| 839 | if (gpio_is_valid(pdata->reset_pin)) | ||
| 840 | gpio_free(pdata->reset_pin); | ||
| 841 | |||
| 842 | kfree(tsdata); | ||
| 843 | |||
| 844 | return 0; | ||
| 845 | } | ||
| 846 | |||
| 847 | #ifdef CONFIG_PM_SLEEP | ||
| 848 | static int edt_ft5x06_ts_suspend(struct device *dev) | ||
| 849 | { | ||
| 850 | struct i2c_client *client = to_i2c_client(dev); | ||
| 851 | |||
| 852 | if (device_may_wakeup(dev)) | ||
| 853 | enable_irq_wake(client->irq); | ||
| 854 | |||
| 855 | return 0; | ||
| 856 | } | ||
| 857 | |||
| 858 | static int edt_ft5x06_ts_resume(struct device *dev) | ||
| 859 | { | ||
| 860 | struct i2c_client *client = to_i2c_client(dev); | ||
| 861 | |||
| 862 | if (device_may_wakeup(dev)) | ||
| 863 | disable_irq_wake(client->irq); | ||
| 864 | |||
| 865 | return 0; | ||
| 866 | } | ||
| 867 | #endif | ||
| 868 | |||
| 869 | static SIMPLE_DEV_PM_OPS(edt_ft5x06_ts_pm_ops, | ||
| 870 | edt_ft5x06_ts_suspend, edt_ft5x06_ts_resume); | ||
| 871 | |||
| 872 | static const struct i2c_device_id edt_ft5x06_ts_id[] = { | ||
| 873 | { "edt-ft5x06", 0 }, | ||
| 874 | { } | ||
| 875 | }; | ||
| 876 | MODULE_DEVICE_TABLE(i2c, edt_ft5x06_ts_id); | ||
| 877 | |||
| 878 | static struct i2c_driver edt_ft5x06_ts_driver = { | ||
| 879 | .driver = { | ||
| 880 | .owner = THIS_MODULE, | ||
| 881 | .name = "edt_ft5x06", | ||
| 882 | .pm = &edt_ft5x06_ts_pm_ops, | ||
| 883 | }, | ||
| 884 | .id_table = edt_ft5x06_ts_id, | ||
| 885 | .probe = edt_ft5x06_ts_probe, | ||
| 886 | .remove = edt_ft5x06_ts_remove, | ||
| 887 | }; | ||
| 888 | |||
| 889 | module_i2c_driver(edt_ft5x06_ts_driver); | ||
| 890 | |||
| 891 | MODULE_AUTHOR("Simon Budig <simon.budig@kernelconcepts.de>"); | ||
| 892 | MODULE_DESCRIPTION("EDT FT5x06 I2C Touchscreen Driver"); | ||
| 893 | MODULE_LICENSE("GPL"); | ||
diff --git a/drivers/input/touchscreen/eeti_ts.c b/drivers/input/touchscreen/eeti_ts.c index 55255a94007..7f8f538a980 100644 --- a/drivers/input/touchscreen/eeti_ts.c +++ b/drivers/input/touchscreen/eeti_ts.c | |||
| @@ -35,11 +35,11 @@ | |||
| 35 | #include <linux/input/eeti_ts.h> | 35 | #include <linux/input/eeti_ts.h> |
| 36 | #include <linux/slab.h> | 36 | #include <linux/slab.h> |
| 37 | 37 | ||
| 38 | static bool flip_x; | 38 | static int flip_x; |
| 39 | module_param(flip_x, bool, 0644); | 39 | module_param(flip_x, bool, 0644); |
| 40 | MODULE_PARM_DESC(flip_x, "flip x coordinate"); | 40 | MODULE_PARM_DESC(flip_x, "flip x coordinate"); |
| 41 | 41 | ||
| 42 | static bool flip_y; | 42 | static int flip_y; |
| 43 | module_param(flip_y, bool, 0644); | 43 | module_param(flip_y, bool, 0644); |
| 44 | MODULE_PARM_DESC(flip_y, "flip y coordinate"); | 44 | MODULE_PARM_DESC(flip_y, "flip y coordinate"); |
| 45 | 45 | ||
| @@ -48,7 +48,7 @@ struct eeti_ts_priv { | |||
| 48 | struct input_dev *input; | 48 | struct input_dev *input; |
| 49 | struct work_struct work; | 49 | struct work_struct work; |
| 50 | struct mutex mutex; | 50 | struct mutex mutex; |
| 51 | int irq_gpio, irq, irq_active_high; | 51 | int irq, irq_active_high; |
| 52 | }; | 52 | }; |
| 53 | 53 | ||
| 54 | #define EETI_TS_BITDEPTH (11) | 54 | #define EETI_TS_BITDEPTH (11) |
| @@ -62,7 +62,7 @@ struct eeti_ts_priv { | |||
| 62 | 62 | ||
| 63 | static inline int eeti_ts_irq_active(struct eeti_ts_priv *priv) | 63 | static inline int eeti_ts_irq_active(struct eeti_ts_priv *priv) |
| 64 | { | 64 | { |
| 65 | return gpio_get_value(priv->irq_gpio) == priv->irq_active_high; | 65 | return gpio_get_value(irq_to_gpio(priv->irq)) == priv->irq_active_high; |
| 66 | } | 66 | } |
| 67 | 67 | ||
| 68 | static void eeti_ts_read(struct work_struct *work) | 68 | static void eeti_ts_read(struct work_struct *work) |
| @@ -154,10 +154,10 @@ static void eeti_ts_close(struct input_dev *dev) | |||
| 154 | eeti_ts_stop(priv); | 154 | eeti_ts_stop(priv); |
| 155 | } | 155 | } |
| 156 | 156 | ||
| 157 | static int eeti_ts_probe(struct i2c_client *client, | 157 | static int __devinit eeti_ts_probe(struct i2c_client *client, |
| 158 | const struct i2c_device_id *idp) | 158 | const struct i2c_device_id *idp) |
| 159 | { | 159 | { |
| 160 | struct eeti_ts_platform_data *pdata = client->dev.platform_data; | 160 | struct eeti_ts_platform_data *pdata; |
| 161 | struct eeti_ts_priv *priv; | 161 | struct eeti_ts_priv *priv; |
| 162 | struct input_dev *input; | 162 | struct input_dev *input; |
| 163 | unsigned int irq_flags; | 163 | unsigned int irq_flags; |
| @@ -199,12 +199,9 @@ static int eeti_ts_probe(struct i2c_client *client, | |||
| 199 | 199 | ||
| 200 | priv->client = client; | 200 | priv->client = client; |
| 201 | priv->input = input; | 201 | priv->input = input; |
| 202 | priv->irq_gpio = pdata->irq_gpio; | 202 | priv->irq = client->irq; |
| 203 | priv->irq = gpio_to_irq(pdata->irq_gpio); | ||
| 204 | 203 | ||
| 205 | err = gpio_request_one(pdata->irq_gpio, GPIOF_IN, client->name); | 204 | pdata = client->dev.platform_data; |
| 206 | if (err < 0) | ||
| 207 | goto err1; | ||
| 208 | 205 | ||
| 209 | if (pdata) | 206 | if (pdata) |
| 210 | priv->irq_active_high = pdata->irq_active_high; | 207 | priv->irq_active_high = pdata->irq_active_high; |
| @@ -218,13 +215,13 @@ static int eeti_ts_probe(struct i2c_client *client, | |||
| 218 | 215 | ||
| 219 | err = input_register_device(input); | 216 | err = input_register_device(input); |
| 220 | if (err) | 217 | if (err) |
| 221 | goto err2; | 218 | goto err1; |
| 222 | 219 | ||
| 223 | err = request_irq(priv->irq, eeti_ts_isr, irq_flags, | 220 | err = request_irq(priv->irq, eeti_ts_isr, irq_flags, |
| 224 | client->name, priv); | 221 | client->name, priv); |
| 225 | if (err) { | 222 | if (err) { |
| 226 | dev_err(&client->dev, "Unable to request touchscreen IRQ.\n"); | 223 | dev_err(&client->dev, "Unable to request touchscreen IRQ.\n"); |
| 227 | goto err3; | 224 | goto err2; |
| 228 | } | 225 | } |
| 229 | 226 | ||
| 230 | /* | 227 | /* |
| @@ -236,11 +233,9 @@ static int eeti_ts_probe(struct i2c_client *client, | |||
| 236 | device_init_wakeup(&client->dev, 0); | 233 | device_init_wakeup(&client->dev, 0); |
| 237 | return 0; | 234 | return 0; |
| 238 | 235 | ||
| 239 | err3: | 236 | err2: |
| 240 | input_unregister_device(input); | 237 | input_unregister_device(input); |
| 241 | input = NULL; /* so we dont try to free it below */ | 238 | input = NULL; /* so we dont try to free it below */ |
| 242 | err2: | ||
| 243 | gpio_free(pdata->irq_gpio); | ||
| 244 | err1: | 239 | err1: |
| 245 | input_free_device(input); | 240 | input_free_device(input); |
| 246 | kfree(priv); | 241 | kfree(priv); |
| @@ -248,7 +243,7 @@ err0: | |||
| 248 | return err; | 243 | return err; |
| 249 | } | 244 | } |
| 250 | 245 | ||
| 251 | static int eeti_ts_remove(struct i2c_client *client) | 246 | static int __devexit eeti_ts_remove(struct i2c_client *client) |
| 252 | { | 247 | { |
| 253 | struct eeti_ts_priv *priv = i2c_get_clientdata(client); | 248 | struct eeti_ts_priv *priv = i2c_get_clientdata(client); |
| 254 | 249 | ||
| @@ -321,12 +316,24 @@ static struct i2c_driver eeti_ts_driver = { | |||
| 321 | #endif | 316 | #endif |
| 322 | }, | 317 | }, |
| 323 | .probe = eeti_ts_probe, | 318 | .probe = eeti_ts_probe, |
| 324 | .remove = eeti_ts_remove, | 319 | .remove = __devexit_p(eeti_ts_remove), |
| 325 | .id_table = eeti_ts_id, | 320 | .id_table = eeti_ts_id, |
| 326 | }; | 321 | }; |
| 327 | 322 | ||
| 328 | module_i2c_driver(eeti_ts_driver); | 323 | static int __init eeti_ts_init(void) |
| 324 | { | ||
| 325 | return i2c_add_driver(&eeti_ts_driver); | ||
| 326 | } | ||
| 327 | |||
| 328 | static void __exit eeti_ts_exit(void) | ||
| 329 | { | ||
| 330 | i2c_del_driver(&eeti_ts_driver); | ||
| 331 | } | ||
| 329 | 332 | ||
| 330 | MODULE_DESCRIPTION("EETI Touchscreen driver"); | 333 | MODULE_DESCRIPTION("EETI Touchscreen driver"); |
| 331 | MODULE_AUTHOR("Daniel Mack <daniel@caiaq.de>"); | 334 | MODULE_AUTHOR("Daniel Mack <daniel@caiaq.de>"); |
| 332 | MODULE_LICENSE("GPL"); | 335 | MODULE_LICENSE("GPL"); |
| 336 | |||
| 337 | module_init(eeti_ts_init); | ||
| 338 | module_exit(eeti_ts_exit); | ||
| 339 | |||
diff --git a/drivers/input/touchscreen/egalax_ts.c b/drivers/input/touchscreen/egalax_ts.c deleted file mode 100644 index 17c9097f3b5..00000000000 --- a/drivers/input/touchscreen/egalax_ts.c +++ /dev/null | |||
| @@ -1,311 +0,0 @@ | |||
| 1 | /* | ||
| 2 | * Driver for EETI eGalax Multiple Touch Controller | ||
| 3 | * | ||
| 4 | * Copyright (C) 2011 Freescale Semiconductor, Inc. | ||
| 5 | * | ||
| 6 | * based on max11801_ts.c | ||
| 7 | * | ||
| 8 | * This program is free software; you can redistribute it and/or modify | ||
| 9 | * it under the terms of the GNU General Public License version 2 as | ||
| 10 | * published by the Free Software Foundation. | ||
| 11 | */ | ||
| 12 | |||
| 13 | /* EETI eGalax serial touch screen controller is a I2C based multiple | ||
| 14 | * touch screen controller, it supports 5 point multiple touch. */ | ||
| 15 | |||
| 16 | /* TODO: | ||
| 17 | - auto idle mode support | ||
| 18 | */ | ||
| 19 | |||
| 20 | #include <linux/module.h> | ||
| 21 | #include <linux/init.h> | ||
| 22 | #include <linux/i2c.h> | ||
| 23 | #include <linux/interrupt.h> | ||
| 24 | #include <linux/input.h> | ||
| 25 | #include <linux/irq.h> | ||
| 26 | #include <linux/gpio.h> | ||
| 27 | #include <linux/delay.h> | ||
| 28 | #include <linux/slab.h> | ||
| 29 | #include <linux/bitops.h> | ||
| 30 | #include <linux/input/mt.h> | ||
| 31 | #include <linux/of_gpio.h> | ||
| 32 | |||
| 33 | /* | ||
| 34 | * Mouse Mode: some panel may configure the controller to mouse mode, | ||
| 35 | * which can only report one point at a given time. | ||
| 36 | * This driver will ignore events in this mode. | ||
| 37 | */ | ||
| 38 | #define REPORT_MODE_MOUSE 0x1 | ||
| 39 | /* | ||
| 40 | * Vendor Mode: this mode is used to transfer some vendor specific | ||
| 41 | * messages. | ||
| 42 | * This driver will ignore events in this mode. | ||
| 43 | */ | ||
| 44 | #define REPORT_MODE_VENDOR 0x3 | ||
| 45 | /* Multiple Touch Mode */ | ||
| 46 | #define REPORT_MODE_MTTOUCH 0x4 | ||
| 47 | |||
| 48 | #define MAX_SUPPORT_POINTS 5 | ||
| 49 | |||
| 50 | #define EVENT_VALID_OFFSET 7 | ||
| 51 | #define EVENT_VALID_MASK (0x1 << EVENT_VALID_OFFSET) | ||
| 52 | #define EVENT_ID_OFFSET 2 | ||
| 53 | #define EVENT_ID_MASK (0xf << EVENT_ID_OFFSET) | ||
| 54 | #define EVENT_IN_RANGE (0x1 << 1) | ||
| 55 | #define EVENT_DOWN_UP (0X1 << 0) | ||
| 56 | |||
| 57 | #define MAX_I2C_DATA_LEN 10 | ||
| 58 | |||
| 59 | #define EGALAX_MAX_X 32760 | ||
| 60 | #define EGALAX_MAX_Y 32760 | ||
| 61 | #define EGALAX_MAX_TRIES 100 | ||
| 62 | |||
| 63 | struct egalax_ts { | ||
| 64 | struct i2c_client *client; | ||
| 65 | struct input_dev *input_dev; | ||
| 66 | }; | ||
| 67 | |||
| 68 | static irqreturn_t egalax_ts_interrupt(int irq, void *dev_id) | ||
| 69 | { | ||
| 70 | struct egalax_ts *ts = dev_id; | ||
| 71 | struct input_dev *input_dev = ts->input_dev; | ||
| 72 | struct i2c_client *client = ts->client; | ||
| 73 | u8 buf[MAX_I2C_DATA_LEN]; | ||
| 74 | int id, ret, x, y, z; | ||
| 75 | int tries = 0; | ||
| 76 | bool down, valid; | ||
| 77 | u8 state; | ||
| 78 | |||
| 79 | do { | ||
| 80 | ret = i2c_master_recv(client, buf, MAX_I2C_DATA_LEN); | ||
| 81 | } while (ret == -EAGAIN && tries++ < EGALAX_MAX_TRIES); | ||
| 82 | |||
| 83 | if (ret < 0) | ||
| 84 | return IRQ_HANDLED; | ||
| 85 | |||
| 86 | if (buf[0] != REPORT_MODE_MTTOUCH) { | ||
| 87 | /* ignore mouse events and vendor events */ | ||
| 88 | return IRQ_HANDLED; | ||
| 89 | } | ||
| 90 | |||
| 91 | state = buf[1]; | ||
| 92 | x = (buf[3] << 8) | buf[2]; | ||
| 93 | y = (buf[5] << 8) | buf[4]; | ||
| 94 | z = (buf[7] << 8) | buf[6]; | ||
| 95 | |||
| 96 | valid = state & EVENT_VALID_MASK; | ||
| 97 | id = (state & EVENT_ID_MASK) >> EVENT_ID_OFFSET; | ||
| 98 | down = state & EVENT_DOWN_UP; | ||
| 99 | |||
| 100 | if (!valid || id > MAX_SUPPORT_POINTS) { | ||
| 101 | dev_dbg(&client->dev, "point invalid\n"); | ||
| 102 | return IRQ_HANDLED; | ||
| 103 | } | ||
| 104 | |||
| 105 | input_mt_slot(input_dev, id); | ||
| 106 | input_mt_report_slot_state(input_dev, MT_TOOL_FINGER, down); | ||
| 107 | |||
| 108 | dev_dbg(&client->dev, "%s id:%d x:%d y:%d z:%d", | ||
| 109 | down ? "down" : "up", id, x, y, z); | ||
| 110 | |||
| 111 | if (down) { | ||
| 112 | input_report_abs(input_dev, ABS_MT_POSITION_X, x); | ||
| 113 | input_report_abs(input_dev, ABS_MT_POSITION_Y, y); | ||
| 114 | input_report_abs(input_dev, ABS_MT_PRESSURE, z); | ||
| 115 | } | ||
| 116 | |||
| 117 | input_mt_report_pointer_emulation(input_dev, true); | ||
| 118 | input_sync(input_dev); | ||
| 119 | |||
| 120 | return IRQ_HANDLED; | ||
| 121 | } | ||
| 122 | |||
| 123 | /* wake up controller by an falling edge of interrupt gpio. */ | ||
| 124 | static int egalax_wake_up_device(struct i2c_client *client) | ||
| 125 | { | ||
| 126 | struct device_node *np = client->dev.of_node; | ||
| 127 | int gpio; | ||
| 128 | int ret; | ||
| 129 | |||
| 130 | if (!np) | ||
| 131 | return -ENODEV; | ||
| 132 | |||
| 133 | gpio = of_get_named_gpio(np, "wakeup-gpios", 0); | ||
| 134 | if (!gpio_is_valid(gpio)) | ||
| 135 | return -ENODEV; | ||
| 136 | |||
| 137 | ret = gpio_request(gpio, "egalax_irq"); | ||
| 138 | if (ret < 0) { | ||
| 139 | dev_err(&client->dev, | ||
| 140 | "request gpio failed, cannot wake up controller: %d\n", | ||
| 141 | ret); | ||
| 142 | return ret; | ||
| 143 | } | ||
| 144 | |||
| 145 | /* wake up controller via an falling edge on IRQ gpio. */ | ||
| 146 | gpio_direction_output(gpio, 0); | ||
| 147 | gpio_set_value(gpio, 1); | ||
| 148 | |||
| 149 | /* controller should be waken up, return irq. */ | ||
| 150 | gpio_direction_input(gpio); | ||
| 151 | gpio_free(gpio); | ||
| 152 | |||
| 153 | return 0; | ||
| 154 | } | ||
| 155 | |||
| 156 | static int egalax_firmware_version(struct i2c_client *client) | ||
| 157 | { | ||
| 158 | static const u8 cmd[MAX_I2C_DATA_LEN] = { 0x03, 0x03, 0xa, 0x01, 0x41 }; | ||
| 159 | int ret; | ||
| 160 | |||
| 161 | ret = i2c_master_send(client, cmd, MAX_I2C_DATA_LEN); | ||
| 162 | if (ret < 0) | ||
| 163 | return ret; | ||
| 164 | |||
| 165 | return 0; | ||
| 166 | } | ||
| 167 | |||
| 168 | static int egalax_ts_probe(struct i2c_client *client, | ||
| 169 | const struct i2c_device_id *id) | ||
| 170 | { | ||
| 171 | struct egalax_ts *ts; | ||
| 172 | struct input_dev *input_dev; | ||
| 173 | int ret; | ||
| 174 | int error; | ||
| 175 | |||
| 176 | ts = kzalloc(sizeof(struct egalax_ts), GFP_KERNEL); | ||
| 177 | if (!ts) { | ||
| 178 | dev_err(&client->dev, "Failed to allocate memory\n"); | ||
| 179 | return -ENOMEM; | ||
| 180 | } | ||
| 181 | |||
| 182 | input_dev = input_allocate_device(); | ||
| 183 | if (!input_dev) { | ||
| 184 | dev_err(&client->dev, "Failed to allocate memory\n"); | ||
| 185 | error = -ENOMEM; | ||
| 186 | goto err_free_ts; | ||
| 187 | } | ||
| 188 | |||
| 189 | ts->client = client; | ||
| 190 | ts->input_dev = input_dev; | ||
| 191 | |||
| 192 | /* controller may be in sleep, wake it up. */ | ||
| 193 | error = egalax_wake_up_device(client); | ||
| 194 | if (error) { | ||
| 195 | dev_err(&client->dev, "Failed to wake up the controller\n"); | ||
| 196 | goto err_free_dev; | ||
| 197 | } | ||
| 198 | |||
| 199 | ret = egalax_firmware_version(client); | ||
| 200 | if (ret < 0) { | ||
| 201 | dev_err(&client->dev, "Failed to read firmware version\n"); | ||
| 202 | error = -EIO; | ||
| 203 | goto err_free_dev; | ||
| 204 | } | ||
| 205 | |||
| 206 | input_dev->name = "EETI eGalax Touch Screen"; | ||
| 207 | input_dev->id.bustype = BUS_I2C; | ||
| 208 | input_dev->dev.parent = &client->dev; | ||
| 209 | |||
| 210 | __set_bit(EV_ABS, input_dev->evbit); | ||
| 211 | __set_bit(EV_KEY, input_dev->evbit); | ||
| 212 | __set_bit(BTN_TOUCH, input_dev->keybit); | ||
| 213 | |||
| 214 | input_set_abs_params(input_dev, ABS_X, 0, EGALAX_MAX_X, 0, 0); | ||
| 215 | input_set_abs_params(input_dev, ABS_Y, 0, EGALAX_MAX_Y, 0, 0); | ||
| 216 | input_set_abs_params(input_dev, | ||
| 217 | ABS_MT_POSITION_X, 0, EGALAX_MAX_X, 0, 0); | ||
| 218 | input_set_abs_params(input_dev, | ||
| 219 | ABS_MT_POSITION_X, 0, EGALAX_MAX_Y, 0, 0); | ||
| 220 | input_mt_init_slots(input_dev, MAX_SUPPORT_POINTS, 0); | ||
| 221 | |||
| 222 | input_set_drvdata(input_dev, ts); | ||
| 223 | |||
| 224 | error = request_threaded_irq(client->irq, NULL, egalax_ts_interrupt, | ||
| 225 | IRQF_TRIGGER_LOW | IRQF_ONESHOT, | ||
| 226 | "egalax_ts", ts); | ||
| 227 | if (error < 0) { | ||
| 228 | dev_err(&client->dev, "Failed to register interrupt\n"); | ||
| 229 | goto err_free_dev; | ||
| 230 | } | ||
| 231 | |||
| 232 | error = input_register_device(ts->input_dev); | ||
| 233 | if (error) | ||
| 234 | goto err_free_irq; | ||
| 235 | |||
| 236 | i2c_set_clientdata(client, ts); | ||
| 237 | return 0; | ||
| 238 | |||
| 239 | err_free_irq: | ||
| 240 | free_irq(client->irq, ts); | ||
| 241 | err_free_dev: | ||
| 242 | input_free_device(input_dev); | ||
| 243 | err_free_ts: | ||
| 244 | kfree(ts); | ||
| 245 | |||
| 246 | return error; | ||
| 247 | } | ||
| 248 | |||
| 249 | static int egalax_ts_remove(struct i2c_client *client) | ||
| 250 | { | ||
| 251 | struct egalax_ts *ts = i2c_get_clientdata(client); | ||
| 252 | |||
| 253 | free_irq(client->irq, ts); | ||
| 254 | |||
| 255 | input_unregister_device(ts->input_dev); | ||
| 256 | kfree(ts); | ||
| 257 | |||
| 258 | return 0; | ||
| 259 | } | ||
| 260 | |||
| 261 | static const struct i2c_device_id egalax_ts_id[] = { | ||
| 262 | { "egalax_ts", 0 }, | ||
| 263 | { } | ||
| 264 | }; | ||
| 265 | MODULE_DEVICE_TABLE(i2c, egalax_ts_id); | ||
| 266 | |||
| 267 | #ifdef CONFIG_PM_SLEEP | ||
| 268 | static int egalax_ts_suspend(struct device *dev) | ||
| 269 | { | ||
| 270 | static const u8 suspend_cmd[MAX_I2C_DATA_LEN] = { | ||
| 271 | 0x3, 0x6, 0xa, 0x3, 0x36, 0x3f, 0x2, 0, 0, 0 | ||
| 272 | }; | ||
| 273 | struct i2c_client *client = to_i2c_client(dev); | ||
| 274 | int ret; | ||
| 275 | |||
| 276 | ret = i2c_master_send(client, suspend_cmd, MAX_I2C_DATA_LEN); | ||
| 277 | return ret > 0 ? 0 : ret; | ||
| 278 | } | ||
| 279 | |||
| 280 | static int egalax_ts_resume(struct device *dev) | ||
| 281 | { | ||
| 282 | struct i2c_client *client = to_i2c_client(dev); | ||
| 283 | |||
| 284 | return egalax_wake_up_device(client); | ||
| 285 | } | ||
| 286 | #endif | ||
| 287 | |||
| 288 | static SIMPLE_DEV_PM_OPS(egalax_ts_pm_ops, egalax_ts_suspend, egalax_ts_resume); | ||
| 289 | |||
| 290 | static struct of_device_id egalax_ts_dt_ids[] = { | ||
| 291 | { .compatible = "eeti,egalax_ts" }, | ||
| 292 | { /* sentinel */ } | ||
| 293 | }; | ||
| 294 | |||
| 295 | static struct i2c_driver egalax_ts_driver = { | ||
| 296 | .driver = { | ||
| 297 | .name = "egalax_ts", | ||
| 298 | .owner = THIS_MODULE, | ||
| 299 | .pm = &egalax_ts_pm_ops, | ||
| 300 | .of_match_table = of_match_ptr(egalax_ts_dt_ids), | ||
| 301 | }, | ||
| 302 | .id_table = egalax_ts_id, | ||
| 303 | .probe = egalax_ts_probe, | ||
| 304 | .remove = egalax_ts_remove, | ||
| 305 | }; | ||
| 306 | |||
| 307 | module_i2c_driver(egalax_ts_driver); | ||
| 308 | |||
| 309 | MODULE_AUTHOR("Freescale Semiconductor, Inc."); | ||
| 310 | MODULE_DESCRIPTION("Touchscreen driver for EETI eGalax touch controller"); | ||
| 311 | MODULE_LICENSE("GPL"); | ||
diff --git a/drivers/input/touchscreen/elo.c b/drivers/input/touchscreen/elo.c index 957423d1471..486d31ba9c0 100644 --- a/drivers/input/touchscreen/elo.c +++ b/drivers/input/touchscreen/elo.c | |||
| @@ -405,4 +405,19 @@ static struct serio_driver elo_drv = { | |||
| 405 | .disconnect = elo_disconnect, | 405 | .disconnect = elo_disconnect, |
| 406 | }; | 406 | }; |
| 407 | 407 | ||
| 408 | module_serio_driver(elo_drv); | 408 | /* |
| 409 | * The functions for inserting/removing us as a module. | ||
| 410 | */ | ||
| 411 | |||
| 412 | static int __init elo_init(void) | ||
| 413 | { | ||
| 414 | return serio_register_driver(&elo_drv); | ||
| 415 | } | ||
| 416 | |||
| 417 | static void __exit elo_exit(void) | ||
| 418 | { | ||
| 419 | serio_unregister_driver(&elo_drv); | ||
| 420 | } | ||
| 421 | |||
| 422 | module_init(elo_init); | ||
| 423 | module_exit(elo_exit); | ||
diff --git a/drivers/input/touchscreen/fujitsu_ts.c b/drivers/input/touchscreen/fujitsu_ts.c index 10794ddbdf5..80b21800355 100644 --- a/drivers/input/touchscreen/fujitsu_ts.c +++ b/drivers/input/touchscreen/fujitsu_ts.c | |||
| @@ -175,4 +175,15 @@ static struct serio_driver fujitsu_drv = { | |||
| 175 | .disconnect = fujitsu_disconnect, | 175 | .disconnect = fujitsu_disconnect, |
| 176 | }; | 176 | }; |
| 177 | 177 | ||
| 178 | module_serio_driver(fujitsu_drv); | 178 | static int __init fujitsu_init(void) |
| 179 | { | ||
| 180 | return serio_register_driver(&fujitsu_drv); | ||
| 181 | } | ||
| 182 | |||
| 183 | static void __exit fujitsu_exit(void) | ||
| 184 | { | ||
| 185 | serio_unregister_driver(&fujitsu_drv); | ||
| 186 | } | ||
| 187 | |||
| 188 | module_init(fujitsu_init); | ||
| 189 | module_exit(fujitsu_exit); | ||
diff --git a/drivers/input/touchscreen/gunze.c b/drivers/input/touchscreen/gunze.c index 41c71766bf1..a54f90e02ab 100644 --- a/drivers/input/touchscreen/gunze.c +++ b/drivers/input/touchscreen/gunze.c | |||
| @@ -186,4 +186,19 @@ static struct serio_driver gunze_drv = { | |||
| 186 | .disconnect = gunze_disconnect, | 186 | .disconnect = gunze_disconnect, |
| 187 | }; | 187 | }; |
| 188 | 188 | ||
| 189 | module_serio_driver(gunze_drv); | 189 | /* |
| 190 | * The functions for inserting/removing us as a module. | ||
| 191 | */ | ||
| 192 | |||
| 193 | static int __init gunze_init(void) | ||
| 194 | { | ||
| 195 | return serio_register_driver(&gunze_drv); | ||
| 196 | } | ||
| 197 | |||
| 198 | static void __exit gunze_exit(void) | ||
| 199 | { | ||
| 200 | serio_unregister_driver(&gunze_drv); | ||
| 201 | } | ||
| 202 | |||
| 203 | module_init(gunze_init); | ||
| 204 | module_exit(gunze_exit); | ||
diff --git a/drivers/input/touchscreen/hampshire.c b/drivers/input/touchscreen/hampshire.c index 0cc47ea98ac..2da6cc31bb2 100644 --- a/drivers/input/touchscreen/hampshire.c +++ b/drivers/input/touchscreen/hampshire.c | |||
| @@ -187,4 +187,19 @@ static struct serio_driver hampshire_drv = { | |||
| 187 | .disconnect = hampshire_disconnect, | 187 | .disconnect = hampshire_disconnect, |
| 188 | }; | 188 | }; |
| 189 | 189 | ||
| 190 | module_serio_driver(hampshire_drv); | 190 | /* |
| 191 | * The functions for inserting/removing us as a module. | ||
| 192 | */ | ||
| 193 | |||
| 194 | static int __init hampshire_init(void) | ||
| 195 | { | ||
| 196 | return serio_register_driver(&hampshire_drv); | ||
| 197 | } | ||
| 198 | |||
| 199 | static void __exit hampshire_exit(void) | ||
| 200 | { | ||
| 201 | serio_unregister_driver(&hampshire_drv); | ||
| 202 | } | ||
| 203 | |||
| 204 | module_init(hampshire_init); | ||
| 205 | module_exit(hampshire_exit); | ||
diff --git a/drivers/input/touchscreen/hp680_ts_input.c b/drivers/input/touchscreen/hp680_ts_input.c index 85cf9bee801..dd4e8f020b9 100644 --- a/drivers/input/touchscreen/hp680_ts_input.c +++ b/drivers/input/touchscreen/hp680_ts_input.c | |||
| @@ -93,7 +93,7 @@ static int __init hp680_ts_init(void) | |||
| 93 | hp680_ts_dev->phys = "hp680_ts/input0"; | 93 | hp680_ts_dev->phys = "hp680_ts/input0"; |
| 94 | 94 | ||
| 95 | if (request_irq(HP680_TS_IRQ, hp680_ts_interrupt, | 95 | if (request_irq(HP680_TS_IRQ, hp680_ts_interrupt, |
| 96 | 0, MODNAME, NULL) < 0) { | 96 | IRQF_DISABLED, MODNAME, 0) < 0) { |
| 97 | printk(KERN_ERR "hp680_touchscreen.c: Can't allocate irq %d\n", | 97 | printk(KERN_ERR "hp680_touchscreen.c: Can't allocate irq %d\n", |
| 98 | HP680_TS_IRQ); | 98 | HP680_TS_IRQ); |
| 99 | err = -EBUSY; | 99 | err = -EBUSY; |
diff --git a/drivers/input/touchscreen/htcpen.c b/drivers/input/touchscreen/htcpen.c index 6c4fb843695..62811de6f18 100644 --- a/drivers/input/touchscreen/htcpen.c +++ b/drivers/input/touchscreen/htcpen.c | |||
| @@ -40,13 +40,19 @@ MODULE_LICENSE("GPL"); | |||
| 40 | #define X_AXIS_MAX 2040 | 40 | #define X_AXIS_MAX 2040 |
| 41 | #define Y_AXIS_MAX 2040 | 41 | #define Y_AXIS_MAX 2040 |
| 42 | 42 | ||
| 43 | static bool invert_x; | 43 | static int invert_x; |
| 44 | module_param(invert_x, bool, 0644); | 44 | module_param(invert_x, bool, 0644); |
| 45 | MODULE_PARM_DESC(invert_x, "If set, X axis is inverted"); | 45 | MODULE_PARM_DESC(invert_x, "If set, X axis is inverted"); |
| 46 | static bool invert_y; | 46 | static int invert_y; |
| 47 | module_param(invert_y, bool, 0644); | 47 | module_param(invert_y, bool, 0644); |
| 48 | MODULE_PARM_DESC(invert_y, "If set, Y axis is inverted"); | 48 | MODULE_PARM_DESC(invert_y, "If set, Y axis is inverted"); |
| 49 | 49 | ||
| 50 | static struct pnp_device_id pnp_ids[] = { | ||
| 51 | { .id = "PNP0cc0" }, | ||
| 52 | { .id = "" } | ||
| 53 | }; | ||
| 54 | MODULE_DEVICE_TABLE(pnp, pnp_ids); | ||
| 55 | |||
| 50 | static irqreturn_t htcpen_interrupt(int irq, void *handle) | 56 | static irqreturn_t htcpen_interrupt(int irq, void *handle) |
| 51 | { | 57 | { |
| 52 | struct input_dev *htcpen_dev = handle; | 58 | struct input_dev *htcpen_dev = handle; |
| @@ -102,7 +108,7 @@ static void htcpen_close(struct input_dev *dev) | |||
| 102 | synchronize_irq(HTCPEN_IRQ); | 108 | synchronize_irq(HTCPEN_IRQ); |
| 103 | } | 109 | } |
| 104 | 110 | ||
| 105 | static int htcpen_isa_probe(struct device *dev, unsigned int id) | 111 | static int __devinit htcpen_isa_probe(struct device *dev, unsigned int id) |
| 106 | { | 112 | { |
| 107 | struct input_dev *htcpen_dev; | 113 | struct input_dev *htcpen_dev; |
| 108 | int err = -EBUSY; | 114 | int err = -EBUSY; |
| @@ -174,7 +180,7 @@ static int htcpen_isa_probe(struct device *dev, unsigned int id) | |||
| 174 | return err; | 180 | return err; |
| 175 | } | 181 | } |
| 176 | 182 | ||
| 177 | static int htcpen_isa_remove(struct device *dev, unsigned int id) | 183 | static int __devexit htcpen_isa_remove(struct device *dev, unsigned int id) |
| 178 | { | 184 | { |
| 179 | struct input_dev *htcpen_dev = dev_get_drvdata(dev); | 185 | struct input_dev *htcpen_dev = dev_get_drvdata(dev); |
| 180 | 186 | ||
| @@ -210,7 +216,7 @@ static int htcpen_isa_resume(struct device *dev, unsigned int n) | |||
| 210 | 216 | ||
| 211 | static struct isa_driver htcpen_isa_driver = { | 217 | static struct isa_driver htcpen_isa_driver = { |
| 212 | .probe = htcpen_isa_probe, | 218 | .probe = htcpen_isa_probe, |
| 213 | .remove = htcpen_isa_remove, | 219 | .remove = __devexit_p(htcpen_isa_remove), |
| 214 | #ifdef CONFIG_PM | 220 | #ifdef CONFIG_PM |
| 215 | .suspend = htcpen_isa_suspend, | 221 | .suspend = htcpen_isa_suspend, |
| 216 | .resume = htcpen_isa_resume, | 222 | .resume = htcpen_isa_resume, |
| @@ -231,7 +237,6 @@ static struct dmi_system_id __initdata htcshift_dmi_table[] = { | |||
| 231 | }, | 237 | }, |
| 232 | { } | 238 | { } |
| 233 | }; | 239 | }; |
| 234 | MODULE_DEVICE_TABLE(dmi, htcshift_dmi_table); | ||
| 235 | 240 | ||
| 236 | static int __init htcpen_isa_init(void) | 241 | static int __init htcpen_isa_init(void) |
| 237 | { | 242 | { |
diff --git a/drivers/input/touchscreen/ili210x.c b/drivers/input/touchscreen/ili210x.c deleted file mode 100644 index 1418bdda61b..00000000000 --- a/drivers/input/touchscreen/ili210x.c +++ /dev/null | |||
| @@ -1,360 +0,0 @@ | |||
| 1 | #include <linux/module.h> | ||
| 2 | #include <linux/i2c.h> | ||
| 3 | #include <linux/interrupt.h> | ||
| 4 | #include <linux/slab.h> | ||
| 5 | #include <linux/input.h> | ||
| 6 | #include <linux/input/mt.h> | ||
| 7 | #include <linux/delay.h> | ||
| 8 | #include <linux/workqueue.h> | ||
| 9 | #include <linux/input/ili210x.h> | ||
| 10 | |||
| 11 | #define MAX_TOUCHES 2 | ||
| 12 | #define DEFAULT_POLL_PERIOD 20 | ||
| 13 | |||
| 14 | /* Touchscreen commands */ | ||
| 15 | #define REG_TOUCHDATA 0x10 | ||
| 16 | #define REG_PANEL_INFO 0x20 | ||
| 17 | #define REG_FIRMWARE_VERSION 0x40 | ||
| 18 | #define REG_CALIBRATE 0xcc | ||
| 19 | |||
| 20 | struct finger { | ||
| 21 | u8 x_low; | ||
| 22 | u8 x_high; | ||
| 23 | u8 y_low; | ||
| 24 | u8 y_high; | ||
| 25 | } __packed; | ||
| 26 | |||
| 27 | struct touchdata { | ||
| 28 | u8 status; | ||
| 29 | struct finger finger[MAX_TOUCHES]; | ||
| 30 | } __packed; | ||
| 31 | |||
| 32 | struct panel_info { | ||
| 33 | struct finger finger_max; | ||
| 34 | u8 xchannel_num; | ||
| 35 | u8 ychannel_num; | ||
| 36 | } __packed; | ||
| 37 | |||
| 38 | struct firmware_version { | ||
| 39 | u8 id; | ||
| 40 | u8 major; | ||
| 41 | u8 minor; | ||
| 42 | } __packed; | ||
| 43 | |||
| 44 | struct ili210x { | ||
| 45 | struct i2c_client *client; | ||
| 46 | struct input_dev *input; | ||
| 47 | bool (*get_pendown_state)(void); | ||
| 48 | unsigned int poll_period; | ||
| 49 | struct delayed_work dwork; | ||
| 50 | }; | ||
| 51 | |||
| 52 | static int ili210x_read_reg(struct i2c_client *client, u8 reg, void *buf, | ||
| 53 | size_t len) | ||
| 54 | { | ||
| 55 | struct i2c_msg msg[2] = { | ||
| 56 | { | ||
| 57 | .addr = client->addr, | ||
| 58 | .flags = 0, | ||
| 59 | .len = 1, | ||
| 60 | .buf = ®, | ||
| 61 | }, | ||
| 62 | { | ||
| 63 | .addr = client->addr, | ||
| 64 | .flags = I2C_M_RD, | ||
| 65 | .len = len, | ||
| 66 | .buf = buf, | ||
| 67 | } | ||
| 68 | }; | ||
| 69 | |||
| 70 | if (i2c_transfer(client->adapter, msg, 2) != 2) { | ||
| 71 | dev_err(&client->dev, "i2c transfer failed\n"); | ||
| 72 | return -EIO; | ||
| 73 | } | ||
| 74 | |||
| 75 | return 0; | ||
| 76 | } | ||
| 77 | |||
| 78 | static void ili210x_report_events(struct input_dev *input, | ||
| 79 | const struct touchdata *touchdata) | ||
| 80 | { | ||
| 81 | int i; | ||
| 82 | bool touch; | ||
| 83 | unsigned int x, y; | ||
| 84 | const struct finger *finger; | ||
| 85 | |||
| 86 | for (i = 0; i < MAX_TOUCHES; i++) { | ||
| 87 | input_mt_slot(input, i); | ||
| 88 | |||
| 89 | finger = &touchdata->finger[i]; | ||
| 90 | |||
| 91 | touch = touchdata->status & (1 << i); | ||
| 92 | input_mt_report_slot_state(input, MT_TOOL_FINGER, touch); | ||
| 93 | if (touch) { | ||
| 94 | x = finger->x_low | (finger->x_high << 8); | ||
| 95 | y = finger->y_low | (finger->y_high << 8); | ||
| 96 | |||
| 97 | input_report_abs(input, ABS_MT_POSITION_X, x); | ||
| 98 | input_report_abs(input, ABS_MT_POSITION_Y, y); | ||
| 99 | } | ||
| 100 | } | ||
| 101 | |||
| 102 | input_mt_report_pointer_emulation(input, false); | ||
| 103 | input_sync(input); | ||
| 104 | } | ||
| 105 | |||
| 106 | static bool get_pendown_state(const struct ili210x *priv) | ||
| 107 | { | ||
| 108 | bool state = false; | ||
| 109 | |||
| 110 | if (priv->get_pendown_state) | ||
| 111 | state = priv->get_pendown_state(); | ||
| 112 | |||
| 113 | return state; | ||
| 114 | } | ||
| 115 | |||
| 116 | static void ili210x_work(struct work_struct *work) | ||
| 117 | { | ||
| 118 | struct ili210x *priv = container_of(work, struct ili210x, | ||
| 119 | dwork.work); | ||
| 120 | struct i2c_client *client = priv->client; | ||
| 121 | struct touchdata touchdata; | ||
| 122 | int error; | ||
| 123 | |||
| 124 | error = ili210x_read_reg(client, REG_TOUCHDATA, | ||
| 125 | &touchdata, sizeof(touchdata)); | ||
| 126 | if (error) { | ||
| 127 | dev_err(&client->dev, | ||
| 128 | "Unable to get touchdata, err = %d\n", error); | ||
| 129 | return; | ||
| 130 | } | ||
| 131 | |||
| 132 | ili210x_report_events(priv->input, &touchdata); | ||
| 133 | |||
| 134 | if ((touchdata.status & 0xf3) || get_pendown_state(priv)) | ||
| 135 | schedule_delayed_work(&priv->dwork, | ||
| 136 | msecs_to_jiffies(priv->poll_period)); | ||
| 137 | } | ||
| 138 | |||
| 139 | static irqreturn_t ili210x_irq(int irq, void *irq_data) | ||
| 140 | { | ||
| 141 | struct ili210x *priv = irq_data; | ||
| 142 | |||
| 143 | schedule_delayed_work(&priv->dwork, 0); | ||
| 144 | |||
| 145 | return IRQ_HANDLED; | ||
| 146 | } | ||
| 147 | |||
| 148 | static ssize_t ili210x_calibrate(struct device *dev, | ||
| 149 | struct device_attribute *attr, | ||
| 150 | const char *buf, size_t count) | ||
| 151 | { | ||
| 152 | struct i2c_client *client = to_i2c_client(dev); | ||
| 153 | struct ili210x *priv = i2c_get_clientdata(client); | ||
| 154 | unsigned long calibrate; | ||
| 155 | int rc; | ||
| 156 | u8 cmd = REG_CALIBRATE; | ||
| 157 | |||
| 158 | if (kstrtoul(buf, 10, &calibrate)) | ||
| 159 | return -EINVAL; | ||
| 160 | |||
| 161 | if (calibrate > 1) | ||
| 162 | return -EINVAL; | ||
| 163 | |||
| 164 | if (calibrate) { | ||
| 165 | rc = i2c_master_send(priv->client, &cmd, sizeof(cmd)); | ||
| 166 | if (rc != sizeof(cmd)) | ||
| 167 | return -EIO; | ||
| 168 | } | ||
| 169 | |||
| 170 | return count; | ||
| 171 | } | ||
| 172 | static DEVICE_ATTR(calibrate, 0644, NULL, ili210x_calibrate); | ||
| 173 | |||
| 174 | static struct attribute *ili210x_attributes[] = { | ||
| 175 | &dev_attr_calibrate.attr, | ||
| 176 | NULL, | ||
| 177 | }; | ||
| 178 | |||
| 179 | static const struct attribute_group ili210x_attr_group = { | ||
| 180 | .attrs = ili210x_attributes, | ||
| 181 | }; | ||
| 182 | |||
| 183 | static int ili210x_i2c_probe(struct i2c_client *client, | ||
| 184 | const struct i2c_device_id *id) | ||
| 185 | { | ||
| 186 | struct device *dev = &client->dev; | ||
| 187 | const struct ili210x_platform_data *pdata = dev->platform_data; | ||
| 188 | struct ili210x *priv; | ||
| 189 | struct input_dev *input; | ||
| 190 | struct panel_info panel; | ||
| 191 | struct firmware_version firmware; | ||
| 192 | int xmax, ymax; | ||
| 193 | int error; | ||
| 194 | |||
| 195 | dev_dbg(dev, "Probing for ILI210X I2C Touschreen driver"); | ||
| 196 | |||
| 197 | if (!pdata) { | ||
| 198 | dev_err(dev, "No platform data!\n"); | ||
| 199 | return -EINVAL; | ||
| 200 | } | ||
| 201 | |||
| 202 | if (client->irq <= 0) { | ||
| 203 | dev_err(dev, "No IRQ!\n"); | ||
| 204 | return -EINVAL; | ||
| 205 | } | ||
| 206 | |||
| 207 | /* Get firmware version */ | ||
| 208 | error = ili210x_read_reg(client, REG_FIRMWARE_VERSION, | ||
| 209 | &firmware, sizeof(firmware)); | ||
| 210 | if (error) { | ||
| 211 | dev_err(dev, "Failed to get firmware version, err: %d\n", | ||
| 212 | error); | ||
| 213 | return error; | ||
| 214 | } | ||
| 215 | |||
| 216 | /* get panel info */ | ||
| 217 | error = ili210x_read_reg(client, REG_PANEL_INFO, &panel, sizeof(panel)); | ||
| 218 | if (error) { | ||
| 219 | dev_err(dev, "Failed to get panel informations, err: %d\n", | ||
| 220 | error); | ||
| 221 | return error; | ||
| 222 | } | ||
| 223 | |||
| 224 | xmax = panel.finger_max.x_low | (panel.finger_max.x_high << 8); | ||
| 225 | ymax = panel.finger_max.y_low | (panel.finger_max.y_high << 8); | ||
| 226 | |||
| 227 | priv = kzalloc(sizeof(*priv), GFP_KERNEL); | ||
| 228 | input = input_allocate_device(); | ||
| 229 | if (!priv || !input) { | ||
| 230 | error = -ENOMEM; | ||
| 231 | goto err_free_mem; | ||
| 232 | } | ||
| 233 | |||
| 234 | priv->client = client; | ||
| 235 | priv->input = input; | ||
| 236 | priv->get_pendown_state = pdata->get_pendown_state; | ||
| 237 | priv->poll_period = pdata->poll_period ? : DEFAULT_POLL_PERIOD; | ||
| 238 | INIT_DELAYED_WORK(&priv->dwork, ili210x_work); | ||
| 239 | |||
| 240 | /* Setup input device */ | ||
| 241 | input->name = "ILI210x Touchscreen"; | ||
| 242 | input->id.bustype = BUS_I2C; | ||
| 243 | input->dev.parent = dev; | ||
| 244 | |||
| 245 | __set_bit(EV_SYN, input->evbit); | ||
| 246 | __set_bit(EV_KEY, input->evbit); | ||
| 247 | __set_bit(EV_ABS, input->evbit); | ||
| 248 | __set_bit(BTN_TOUCH, input->keybit); | ||
| 249 | |||
| 250 | /* Single touch */ | ||
| 251 | input_set_abs_params(input, ABS_X, 0, xmax, 0, 0); | ||
| 252 | input_set_abs_params(input, ABS_Y, 0, ymax, 0, 0); | ||
| 253 | |||
| 254 | /* Multi touch */ | ||
| 255 | input_mt_init_slots(input, MAX_TOUCHES, 0); | ||
| 256 | input_set_abs_params(input, ABS_MT_POSITION_X, 0, xmax, 0, 0); | ||
| 257 | input_set_abs_params(input, ABS_MT_POSITION_Y, 0, ymax, 0, 0); | ||
| 258 | |||
| 259 | input_set_drvdata(input, priv); | ||
| 260 | i2c_set_clientdata(client, priv); | ||
| 261 | |||
| 262 | error = request_irq(client->irq, ili210x_irq, pdata->irq_flags, | ||
| 263 | client->name, priv); | ||
| 264 | if (error) { | ||
| 265 | dev_err(dev, "Unable to request touchscreen IRQ, err: %d\n", | ||
| 266 | error); | ||
| 267 | goto err_free_mem; | ||
| 268 | } | ||
| 269 | |||
| 270 | error = sysfs_create_group(&dev->kobj, &ili210x_attr_group); | ||
| 271 | if (error) { | ||
| 272 | dev_err(dev, "Unable to create sysfs attributes, err: %d\n", | ||
| 273 | error); | ||
| 274 | goto err_free_irq; | ||
| 275 | } | ||
| 276 | |||
| 277 | error = input_register_device(priv->input); | ||
| 278 | if (error) { | ||
| 279 | dev_err(dev, "Cannot regiser input device, err: %d\n", error); | ||
| 280 | goto err_remove_sysfs; | ||
| 281 | } | ||
| 282 | |||
| 283 | device_init_wakeup(&client->dev, 1); | ||
| 284 | |||
| 285 | dev_dbg(dev, | ||
| 286 | "ILI210x initialized (IRQ: %d), firmware version %d.%d.%d", | ||
| 287 | client->irq, firmware.id, firmware.major, firmware.minor); | ||
| 288 | |||
| 289 | return 0; | ||
| 290 | |||
| 291 | err_remove_sysfs: | ||
| 292 | sysfs_remove_group(&dev->kobj, &ili210x_attr_group); | ||
| 293 | err_free_irq: | ||
| 294 | free_irq(client->irq, priv); | ||
| 295 | err_free_mem: | ||
| 296 | input_free_device(input); | ||
| 297 | kfree(priv); | ||
| 298 | return error; | ||
| 299 | } | ||
| 300 | |||
| 301 | static int ili210x_i2c_remove(struct i2c_client *client) | ||
| 302 | { | ||
| 303 | struct ili210x *priv = i2c_get_clientdata(client); | ||
| 304 | |||
| 305 | sysfs_remove_group(&client->dev.kobj, &ili210x_attr_group); | ||
| 306 | free_irq(priv->client->irq, priv); | ||
| 307 | cancel_delayed_work_sync(&priv->dwork); | ||
| 308 | input_unregister_device(priv->input); | ||
| 309 | kfree(priv); | ||
| 310 | |||
| 311 | return 0; | ||
| 312 | } | ||
| 313 | |||
| 314 | #ifdef CONFIG_PM_SLEEP | ||
| 315 | static int ili210x_i2c_suspend(struct device *dev) | ||
| 316 | { | ||
| 317 | struct i2c_client *client = to_i2c_client(dev); | ||
| 318 | |||
| 319 | if (device_may_wakeup(&client->dev)) | ||
| 320 | enable_irq_wake(client->irq); | ||
| 321 | |||
| 322 | return 0; | ||
| 323 | } | ||
| 324 | |||
| 325 | static int ili210x_i2c_resume(struct device *dev) | ||
| 326 | { | ||
| 327 | struct i2c_client *client = to_i2c_client(dev); | ||
| 328 | |||
| 329 | if (device_may_wakeup(&client->dev)) | ||
| 330 | disable_irq_wake(client->irq); | ||
| 331 | |||
| 332 | return 0; | ||
| 333 | } | ||
| 334 | #endif | ||
| 335 | |||
| 336 | static SIMPLE_DEV_PM_OPS(ili210x_i2c_pm, | ||
| 337 | ili210x_i2c_suspend, ili210x_i2c_resume); | ||
| 338 | |||
| 339 | static const struct i2c_device_id ili210x_i2c_id[] = { | ||
| 340 | { "ili210x", 0 }, | ||
| 341 | { } | ||
| 342 | }; | ||
| 343 | MODULE_DEVICE_TABLE(i2c, ili210x_i2c_id); | ||
| 344 | |||
| 345 | static struct i2c_driver ili210x_ts_driver = { | ||
| 346 | .driver = { | ||
| 347 | .name = "ili210x_i2c", | ||
| 348 | .owner = THIS_MODULE, | ||
| 349 | .pm = &ili210x_i2c_pm, | ||
| 350 | }, | ||
| 351 | .id_table = ili210x_i2c_id, | ||
| 352 | .probe = ili210x_i2c_probe, | ||
| 353 | .remove = ili210x_i2c_remove, | ||
| 354 | }; | ||
| 355 | |||
| 356 | module_i2c_driver(ili210x_ts_driver); | ||
| 357 | |||
| 358 | MODULE_AUTHOR("Olivier Sobrie <olivier@sobrie.be>"); | ||
| 359 | MODULE_DESCRIPTION("ILI210X I2C Touchscreen Driver"); | ||
| 360 | MODULE_LICENSE("GPL"); | ||
diff --git a/drivers/input/touchscreen/inexio.c b/drivers/input/touchscreen/inexio.c index a29c99c3224..192ade0a0fb 100644 --- a/drivers/input/touchscreen/inexio.c +++ b/drivers/input/touchscreen/inexio.c | |||
| @@ -189,4 +189,19 @@ static struct serio_driver inexio_drv = { | |||
| 189 | .disconnect = inexio_disconnect, | 189 | .disconnect = inexio_disconnect, |
| 190 | }; | 190 | }; |
| 191 | 191 | ||
| 192 | module_serio_driver(inexio_drv); | 192 | /* |
| 193 | * The functions for inserting/removing us as a module. | ||
| 194 | */ | ||
| 195 | |||
| 196 | static int __init inexio_init(void) | ||
| 197 | { | ||
| 198 | return serio_register_driver(&inexio_drv); | ||
| 199 | } | ||
| 200 | |||
| 201 | static void __exit inexio_exit(void) | ||
| 202 | { | ||
| 203 | serio_unregister_driver(&inexio_drv); | ||
| 204 | } | ||
| 205 | |||
| 206 | module_init(inexio_init); | ||
| 207 | module_exit(inexio_exit); | ||
diff --git a/drivers/input/touchscreen/intel-mid-touch.c b/drivers/input/touchscreen/intel-mid-touch.c index 465db5dba8b..327695268e0 100644 --- a/drivers/input/touchscreen/intel-mid-touch.c +++ b/drivers/input/touchscreen/intel-mid-touch.c | |||
| @@ -427,7 +427,7 @@ out: | |||
| 427 | } | 427 | } |
| 428 | 428 | ||
| 429 | /* Utility to read PMIC ID */ | 429 | /* Utility to read PMIC ID */ |
| 430 | static int mrstouch_read_pmic_id(uint *vendor, uint *rev) | 430 | static int __devinit mrstouch_read_pmic_id(uint *vendor, uint *rev) |
| 431 | { | 431 | { |
| 432 | int err; | 432 | int err; |
| 433 | u8 r; | 433 | u8 r; |
| @@ -446,7 +446,7 @@ static int mrstouch_read_pmic_id(uint *vendor, uint *rev) | |||
| 446 | * Parse ADC channels to find end of the channel configured by other ADC user | 446 | * Parse ADC channels to find end of the channel configured by other ADC user |
| 447 | * NEC and MAXIM requires 4 channels and FreeScale needs 18 channels | 447 | * NEC and MAXIM requires 4 channels and FreeScale needs 18 channels |
| 448 | */ | 448 | */ |
| 449 | static int mrstouch_chan_parse(struct mrstouch_dev *tsdev) | 449 | static int __devinit mrstouch_chan_parse(struct mrstouch_dev *tsdev) |
| 450 | { | 450 | { |
| 451 | int found = 0; | 451 | int found = 0; |
| 452 | int err, i; | 452 | int err, i; |
| @@ -478,7 +478,7 @@ static int mrstouch_chan_parse(struct mrstouch_dev *tsdev) | |||
| 478 | /* | 478 | /* |
| 479 | * Writes touch screen channels to ADC address selection registers | 479 | * Writes touch screen channels to ADC address selection registers |
| 480 | */ | 480 | */ |
| 481 | static int mrstouch_ts_chan_set(uint offset) | 481 | static int __devinit mrstouch_ts_chan_set(uint offset) |
| 482 | { | 482 | { |
| 483 | u16 chan; | 483 | u16 chan; |
| 484 | 484 | ||
| @@ -494,7 +494,7 @@ static int mrstouch_ts_chan_set(uint offset) | |||
| 494 | } | 494 | } |
| 495 | 495 | ||
| 496 | /* Initialize ADC */ | 496 | /* Initialize ADC */ |
| 497 | static int mrstouch_adc_init(struct mrstouch_dev *tsdev) | 497 | static int __devinit mrstouch_adc_init(struct mrstouch_dev *tsdev) |
| 498 | { | 498 | { |
| 499 | int err, start; | 499 | int err, start; |
| 500 | u8 ra, rm; | 500 | u8 ra, rm; |
| @@ -568,7 +568,7 @@ static int mrstouch_adc_init(struct mrstouch_dev *tsdev) | |||
| 568 | 568 | ||
| 569 | 569 | ||
| 570 | /* Probe function for touch screen driver */ | 570 | /* Probe function for touch screen driver */ |
| 571 | static int mrstouch_probe(struct platform_device *pdev) | 571 | static int __devinit mrstouch_probe(struct platform_device *pdev) |
| 572 | { | 572 | { |
| 573 | struct mrstouch_dev *tsdev; | 573 | struct mrstouch_dev *tsdev; |
| 574 | struct input_dev *input; | 574 | struct input_dev *input; |
| @@ -620,7 +620,7 @@ static int mrstouch_probe(struct platform_device *pdev) | |||
| 620 | MRST_PRESSURE_MIN, MRST_PRESSURE_MAX, 0, 0); | 620 | MRST_PRESSURE_MIN, MRST_PRESSURE_MAX, 0, 0); |
| 621 | 621 | ||
| 622 | err = request_threaded_irq(tsdev->irq, NULL, mrstouch_pendet_irq, | 622 | err = request_threaded_irq(tsdev->irq, NULL, mrstouch_pendet_irq, |
| 623 | IRQF_ONESHOT, "mrstouch", tsdev); | 623 | 0, "mrstouch", tsdev); |
| 624 | if (err) { | 624 | if (err) { |
| 625 | dev_err(tsdev->dev, "unable to allocate irq\n"); | 625 | dev_err(tsdev->dev, "unable to allocate irq\n"); |
| 626 | goto err_free_mem; | 626 | goto err_free_mem; |
| @@ -643,7 +643,7 @@ err_free_mem: | |||
| 643 | return err; | 643 | return err; |
| 644 | } | 644 | } |
| 645 | 645 | ||
| 646 | static int mrstouch_remove(struct platform_device *pdev) | 646 | static int __devexit mrstouch_remove(struct platform_device *pdev) |
| 647 | { | 647 | { |
| 648 | struct mrstouch_dev *tsdev = platform_get_drvdata(pdev); | 648 | struct mrstouch_dev *tsdev = platform_get_drvdata(pdev); |
| 649 | 649 | ||
| @@ -662,9 +662,20 @@ static struct platform_driver mrstouch_driver = { | |||
| 662 | .owner = THIS_MODULE, | 662 | .owner = THIS_MODULE, |
| 663 | }, | 663 | }, |
| 664 | .probe = mrstouch_probe, | 664 | .probe = mrstouch_probe, |
| 665 | .remove = mrstouch_remove, | 665 | .remove = __devexit_p(mrstouch_remove), |
| 666 | }; | 666 | }; |
| 667 | module_platform_driver(mrstouch_driver); | 667 | |
| 668 | static int __init mrstouch_init(void) | ||
| 669 | { | ||
| 670 | return platform_driver_register(&mrstouch_driver); | ||
| 671 | } | ||
| 672 | module_init(mrstouch_init); | ||
| 673 | |||
| 674 | static void __exit mrstouch_exit(void) | ||
| 675 | { | ||
| 676 | platform_driver_unregister(&mrstouch_driver); | ||
| 677 | } | ||
| 678 | module_exit(mrstouch_exit); | ||
| 668 | 679 | ||
| 669 | MODULE_AUTHOR("Sreedhara Murthy. D.S, sreedhara.ds@intel.com"); | 680 | MODULE_AUTHOR("Sreedhara Murthy. D.S, sreedhara.ds@intel.com"); |
| 670 | MODULE_DESCRIPTION("Intel Moorestown Resistive Touch Screen Driver"); | 681 | MODULE_DESCRIPTION("Intel Moorestown Resistive Touch Screen Driver"); |
diff --git a/drivers/input/touchscreen/jornada720_ts.c b/drivers/input/touchscreen/jornada720_ts.c index 282d7c7ad2f..4b0a061811f 100644 --- a/drivers/input/touchscreen/jornada720_ts.c +++ b/drivers/input/touchscreen/jornada720_ts.c | |||
| @@ -19,11 +19,9 @@ | |||
| 19 | #include <linux/interrupt.h> | 19 | #include <linux/interrupt.h> |
| 20 | #include <linux/module.h> | 20 | #include <linux/module.h> |
| 21 | #include <linux/slab.h> | 21 | #include <linux/slab.h> |
| 22 | #include <linux/io.h> | ||
| 23 | 22 | ||
| 24 | #include <mach/hardware.h> | 23 | #include <mach/hardware.h> |
| 25 | #include <mach/jornada720.h> | 24 | #include <mach/jornada720.h> |
| 26 | #include <mach/irqs.h> | ||
| 27 | 25 | ||
| 28 | MODULE_AUTHOR("Kristoffer Ericson <kristoffer.ericson@gmail.com>"); | 26 | MODULE_AUTHOR("Kristoffer Ericson <kristoffer.ericson@gmail.com>"); |
| 29 | MODULE_DESCRIPTION("HP Jornada 710/720/728 touchscreen driver"); | 27 | MODULE_DESCRIPTION("HP Jornada 710/720/728 touchscreen driver"); |
| @@ -99,7 +97,7 @@ static irqreturn_t jornada720_ts_interrupt(int irq, void *dev_id) | |||
| 99 | return IRQ_HANDLED; | 97 | return IRQ_HANDLED; |
| 100 | } | 98 | } |
| 101 | 99 | ||
| 102 | static int jornada720_ts_probe(struct platform_device *pdev) | 100 | static int __devinit jornada720_ts_probe(struct platform_device *pdev) |
| 103 | { | 101 | { |
| 104 | struct jornada_ts *jornada_ts; | 102 | struct jornada_ts *jornada_ts; |
| 105 | struct input_dev *input_dev; | 103 | struct input_dev *input_dev; |
| @@ -129,7 +127,7 @@ static int jornada720_ts_probe(struct platform_device *pdev) | |||
| 129 | 127 | ||
| 130 | error = request_irq(IRQ_GPIO9, | 128 | error = request_irq(IRQ_GPIO9, |
| 131 | jornada720_ts_interrupt, | 129 | jornada720_ts_interrupt, |
| 132 | IRQF_TRIGGER_RISING, | 130 | IRQF_DISABLED | IRQF_TRIGGER_RISING, |
| 133 | "HP7XX Touchscreen driver", pdev); | 131 | "HP7XX Touchscreen driver", pdev); |
| 134 | if (error) { | 132 | if (error) { |
| 135 | printk(KERN_INFO "HP7XX TS : Unable to acquire irq!\n"); | 133 | printk(KERN_INFO "HP7XX TS : Unable to acquire irq!\n"); |
| @@ -151,7 +149,7 @@ static int jornada720_ts_probe(struct platform_device *pdev) | |||
| 151 | return error; | 149 | return error; |
| 152 | } | 150 | } |
| 153 | 151 | ||
| 154 | static int jornada720_ts_remove(struct platform_device *pdev) | 152 | static int __devexit jornada720_ts_remove(struct platform_device *pdev) |
| 155 | { | 153 | { |
| 156 | struct jornada_ts *jornada_ts = platform_get_drvdata(pdev); | 154 | struct jornada_ts *jornada_ts = platform_get_drvdata(pdev); |
| 157 | 155 | ||
| @@ -168,10 +166,22 @@ MODULE_ALIAS("platform:jornada_ts"); | |||
| 168 | 166 | ||
| 169 | static struct platform_driver jornada720_ts_driver = { | 167 | static struct platform_driver jornada720_ts_driver = { |
| 170 | .probe = jornada720_ts_probe, | 168 | .probe = jornada720_ts_probe, |
| 171 | .remove = jornada720_ts_remove, | 169 | .remove = __devexit_p(jornada720_ts_remove), |
| 172 | .driver = { | 170 | .driver = { |
| 173 | .name = "jornada_ts", | 171 | .name = "jornada_ts", |
| 174 | .owner = THIS_MODULE, | 172 | .owner = THIS_MODULE, |
| 175 | }, | 173 | }, |
| 176 | }; | 174 | }; |
| 177 | module_platform_driver(jornada720_ts_driver); | 175 | |
| 176 | static int __init jornada720_ts_init(void) | ||
| 177 | { | ||
| 178 | return platform_driver_register(&jornada720_ts_driver); | ||
| 179 | } | ||
| 180 | |||
| 181 | static void __exit jornada720_ts_exit(void) | ||
| 182 | { | ||
| 183 | platform_driver_unregister(&jornada720_ts_driver); | ||
| 184 | } | ||
| 185 | |||
| 186 | module_init(jornada720_ts_init); | ||
| 187 | module_exit(jornada720_ts_exit); | ||
diff --git a/drivers/input/touchscreen/lpc32xx_ts.c b/drivers/input/touchscreen/lpc32xx_ts.c index 9101ee529c9..dcf803f5a1f 100644 --- a/drivers/input/touchscreen/lpc32xx_ts.c +++ b/drivers/input/touchscreen/lpc32xx_ts.c | |||
| @@ -22,7 +22,6 @@ | |||
| 22 | #include <linux/clk.h> | 22 | #include <linux/clk.h> |
| 23 | #include <linux/io.h> | 23 | #include <linux/io.h> |
| 24 | #include <linux/slab.h> | 24 | #include <linux/slab.h> |
| 25 | #include <linux/of.h> | ||
| 26 | 25 | ||
| 27 | /* | 26 | /* |
| 28 | * Touchscreen controller register offsets | 27 | * Touchscreen controller register offsets |
| @@ -203,7 +202,7 @@ static void lpc32xx_ts_close(struct input_dev *dev) | |||
| 203 | lpc32xx_stop_tsc(tsc); | 202 | lpc32xx_stop_tsc(tsc); |
| 204 | } | 203 | } |
| 205 | 204 | ||
| 206 | static int lpc32xx_ts_probe(struct platform_device *pdev) | 205 | static int __devinit lpc32xx_ts_probe(struct platform_device *pdev) |
| 207 | { | 206 | { |
| 208 | struct lpc32xx_tsc *tsc; | 207 | struct lpc32xx_tsc *tsc; |
| 209 | struct input_dev *input; | 208 | struct input_dev *input; |
| @@ -277,7 +276,7 @@ static int lpc32xx_ts_probe(struct platform_device *pdev) | |||
| 277 | input_set_drvdata(input, tsc); | 276 | input_set_drvdata(input, tsc); |
| 278 | 277 | ||
| 279 | error = request_irq(tsc->irq, lpc32xx_ts_interrupt, | 278 | error = request_irq(tsc->irq, lpc32xx_ts_interrupt, |
| 280 | 0, pdev->name, tsc); | 279 | IRQF_DISABLED, pdev->name, tsc); |
| 281 | if (error) { | 280 | if (error) { |
| 282 | dev_err(&pdev->dev, "failed requesting interrupt\n"); | 281 | dev_err(&pdev->dev, "failed requesting interrupt\n"); |
| 283 | goto err_put_clock; | 282 | goto err_put_clock; |
| @@ -309,7 +308,7 @@ err_free_mem: | |||
| 309 | return error; | 308 | return error; |
| 310 | } | 309 | } |
| 311 | 310 | ||
| 312 | static int lpc32xx_ts_remove(struct platform_device *pdev) | 311 | static int __devexit lpc32xx_ts_remove(struct platform_device *pdev) |
| 313 | { | 312 | { |
| 314 | struct lpc32xx_tsc *tsc = platform_get_drvdata(pdev); | 313 | struct lpc32xx_tsc *tsc = platform_get_drvdata(pdev); |
| 315 | struct resource *res; | 314 | struct resource *res; |
| @@ -384,25 +383,27 @@ static const struct dev_pm_ops lpc32xx_ts_pm_ops = { | |||
| 384 | #define LPC32XX_TS_PM_OPS NULL | 383 | #define LPC32XX_TS_PM_OPS NULL |
| 385 | #endif | 384 | #endif |
| 386 | 385 | ||
| 387 | #ifdef CONFIG_OF | ||
| 388 | static struct of_device_id lpc32xx_tsc_of_match[] = { | ||
| 389 | { .compatible = "nxp,lpc3220-tsc", }, | ||
| 390 | { }, | ||
| 391 | }; | ||
| 392 | MODULE_DEVICE_TABLE(of, lpc32xx_tsc_of_match); | ||
| 393 | #endif | ||
| 394 | |||
| 395 | static struct platform_driver lpc32xx_ts_driver = { | 386 | static struct platform_driver lpc32xx_ts_driver = { |
| 396 | .probe = lpc32xx_ts_probe, | 387 | .probe = lpc32xx_ts_probe, |
| 397 | .remove = lpc32xx_ts_remove, | 388 | .remove = __devexit_p(lpc32xx_ts_remove), |
| 398 | .driver = { | 389 | .driver = { |
| 399 | .name = MOD_NAME, | 390 | .name = MOD_NAME, |
| 400 | .owner = THIS_MODULE, | 391 | .owner = THIS_MODULE, |
| 401 | .pm = LPC32XX_TS_PM_OPS, | 392 | .pm = LPC32XX_TS_PM_OPS, |
| 402 | .of_match_table = of_match_ptr(lpc32xx_tsc_of_match), | ||
| 403 | }, | 393 | }, |
| 404 | }; | 394 | }; |
| 405 | module_platform_driver(lpc32xx_ts_driver); | 395 | |
| 396 | static int __init lpc32xx_ts_init(void) | ||
| 397 | { | ||
| 398 | return platform_driver_register(&lpc32xx_ts_driver); | ||
| 399 | } | ||
| 400 | module_init(lpc32xx_ts_init); | ||
| 401 | |||
| 402 | static void __exit lpc32xx_ts_exit(void) | ||
| 403 | { | ||
| 404 | platform_driver_unregister(&lpc32xx_ts_driver); | ||
| 405 | } | ||
| 406 | module_exit(lpc32xx_ts_exit); | ||
| 406 | 407 | ||
| 407 | MODULE_AUTHOR("Kevin Wells <kevin.wells@nxp.com"); | 408 | MODULE_AUTHOR("Kevin Wells <kevin.wells@nxp.com"); |
| 408 | MODULE_DESCRIPTION("LPC32XX TSC Driver"); | 409 | MODULE_DESCRIPTION("LPC32XX TSC Driver"); |
diff --git a/drivers/input/touchscreen/mainstone-wm97xx.c b/drivers/input/touchscreen/mainstone-wm97xx.c index 7d2b2136e5a..e966c29ff1b 100644 --- a/drivers/input/touchscreen/mainstone-wm97xx.c +++ b/drivers/input/touchscreen/mainstone-wm97xx.c | |||
| @@ -302,7 +302,19 @@ static struct platform_driver mainstone_wm97xx_driver = { | |||
| 302 | .name = "wm97xx-touch", | 302 | .name = "wm97xx-touch", |
| 303 | }, | 303 | }, |
| 304 | }; | 304 | }; |
| 305 | module_platform_driver(mainstone_wm97xx_driver); | 305 | |
| 306 | static int __init mainstone_wm97xx_init(void) | ||
| 307 | { | ||
| 308 | return platform_driver_register(&mainstone_wm97xx_driver); | ||
| 309 | } | ||
| 310 | |||
| 311 | static void __exit mainstone_wm97xx_exit(void) | ||
| 312 | { | ||
| 313 | platform_driver_unregister(&mainstone_wm97xx_driver); | ||
| 314 | } | ||
| 315 | |||
| 316 | module_init(mainstone_wm97xx_init); | ||
| 317 | module_exit(mainstone_wm97xx_exit); | ||
| 306 | 318 | ||
| 307 | /* Module information */ | 319 | /* Module information */ |
| 308 | MODULE_AUTHOR("Liam Girdwood <lrg@slimlogic.co.uk>"); | 320 | MODULE_AUTHOR("Liam Girdwood <lrg@slimlogic.co.uk>"); |
diff --git a/drivers/input/touchscreen/max11801_ts.c b/drivers/input/touchscreen/max11801_ts.c index 00bc6caa27f..4627fe55b40 100644 --- a/drivers/input/touchscreen/max11801_ts.c +++ b/drivers/input/touchscreen/max11801_ts.c | |||
| @@ -156,7 +156,7 @@ out: | |||
| 156 | return IRQ_HANDLED; | 156 | return IRQ_HANDLED; |
| 157 | } | 157 | } |
| 158 | 158 | ||
| 159 | static void max11801_ts_phy_init(struct max11801_data *data) | 159 | static void __devinit max11801_ts_phy_init(struct max11801_data *data) |
| 160 | { | 160 | { |
| 161 | struct i2c_client *client = data->client; | 161 | struct i2c_client *client = data->client; |
| 162 | 162 | ||
| @@ -174,7 +174,7 @@ static void max11801_ts_phy_init(struct max11801_data *data) | |||
| 174 | max11801_write_reg(client, OP_MODE_CONF_REG, 0x36); | 174 | max11801_write_reg(client, OP_MODE_CONF_REG, 0x36); |
| 175 | } | 175 | } |
| 176 | 176 | ||
| 177 | static int max11801_ts_probe(struct i2c_client *client, | 177 | static int __devinit max11801_ts_probe(struct i2c_client *client, |
| 178 | const struct i2c_device_id *id) | 178 | const struct i2c_device_id *id) |
| 179 | { | 179 | { |
| 180 | struct max11801_data *data; | 180 | struct max11801_data *data; |
| @@ -228,7 +228,7 @@ err_free_mem: | |||
| 228 | return error; | 228 | return error; |
| 229 | } | 229 | } |
| 230 | 230 | ||
| 231 | static int max11801_ts_remove(struct i2c_client *client) | 231 | static __devexit int max11801_ts_remove(struct i2c_client *client) |
| 232 | { | 232 | { |
| 233 | struct max11801_data *data = i2c_get_clientdata(client); | 233 | struct max11801_data *data = i2c_get_clientdata(client); |
| 234 | 234 | ||
| @@ -252,10 +252,21 @@ static struct i2c_driver max11801_ts_driver = { | |||
| 252 | }, | 252 | }, |
| 253 | .id_table = max11801_ts_id, | 253 | .id_table = max11801_ts_id, |
| 254 | .probe = max11801_ts_probe, | 254 | .probe = max11801_ts_probe, |
| 255 | .remove = max11801_ts_remove, | 255 | .remove = __devexit_p(max11801_ts_remove), |
| 256 | }; | 256 | }; |
| 257 | 257 | ||
| 258 | module_i2c_driver(max11801_ts_driver); | 258 | static int __init max11801_ts_init(void) |
| 259 | { | ||
| 260 | return i2c_add_driver(&max11801_ts_driver); | ||
| 261 | } | ||
| 262 | |||
| 263 | static void __exit max11801_ts_exit(void) | ||
| 264 | { | ||
| 265 | i2c_del_driver(&max11801_ts_driver); | ||
| 266 | } | ||
| 267 | |||
| 268 | module_init(max11801_ts_init); | ||
| 269 | module_exit(max11801_ts_exit); | ||
| 259 | 270 | ||
| 260 | MODULE_AUTHOR("Zhang Jiejing <jiejing.zhang@freescale.com>"); | 271 | MODULE_AUTHOR("Zhang Jiejing <jiejing.zhang@freescale.com>"); |
| 261 | MODULE_DESCRIPTION("Touchscreen driver for MAXI MAX11801 controller"); | 272 | MODULE_DESCRIPTION("Touchscreen driver for MAXI MAX11801 controller"); |
diff --git a/drivers/input/touchscreen/mc13783_ts.c b/drivers/input/touchscreen/mc13783_ts.c index 02103b6abb3..c5bc62d85bb 100644 --- a/drivers/input/touchscreen/mc13783_ts.c +++ b/drivers/input/touchscreen/mc13783_ts.c | |||
| @@ -35,18 +35,17 @@ MODULE_PARM_DESC(sample_tolerance, | |||
| 35 | 35 | ||
| 36 | struct mc13783_ts_priv { | 36 | struct mc13783_ts_priv { |
| 37 | struct input_dev *idev; | 37 | struct input_dev *idev; |
| 38 | struct mc13xxx *mc13xxx; | 38 | struct mc13783 *mc13783; |
| 39 | struct delayed_work work; | 39 | struct delayed_work work; |
| 40 | struct workqueue_struct *workq; | 40 | struct workqueue_struct *workq; |
| 41 | unsigned int sample[4]; | 41 | unsigned int sample[4]; |
| 42 | struct mc13xxx_ts_platform_data *touch; | ||
| 43 | }; | 42 | }; |
| 44 | 43 | ||
| 45 | static irqreturn_t mc13783_ts_handler(int irq, void *data) | 44 | static irqreturn_t mc13783_ts_handler(int irq, void *data) |
| 46 | { | 45 | { |
| 47 | struct mc13783_ts_priv *priv = data; | 46 | struct mc13783_ts_priv *priv = data; |
| 48 | 47 | ||
| 49 | mc13xxx_irq_ack(priv->mc13xxx, irq); | 48 | mc13783_irq_ack(priv->mc13783, irq); |
| 50 | 49 | ||
| 51 | /* | 50 | /* |
| 52 | * Kick off reading coordinates. Note that if work happens already | 51 | * Kick off reading coordinates. Note that if work happens already |
| @@ -122,13 +121,11 @@ static void mc13783_ts_work(struct work_struct *work) | |||
| 122 | { | 121 | { |
| 123 | struct mc13783_ts_priv *priv = | 122 | struct mc13783_ts_priv *priv = |
| 124 | container_of(work, struct mc13783_ts_priv, work.work); | 123 | container_of(work, struct mc13783_ts_priv, work.work); |
| 125 | unsigned int mode = MC13XXX_ADC_MODE_TS; | 124 | unsigned int mode = MC13783_ADC_MODE_TS; |
| 126 | unsigned int channel = 12; | 125 | unsigned int channel = 12; |
| 127 | 126 | ||
| 128 | if (mc13xxx_adc_do_conversion(priv->mc13xxx, | 127 | if (mc13783_adc_do_conversion(priv->mc13783, |
| 129 | mode, channel, | 128 | mode, channel, priv->sample) == 0) |
| 130 | priv->touch->ato, priv->touch->atox, | ||
| 131 | priv->sample) == 0) | ||
| 132 | mc13783_ts_report_sample(priv); | 129 | mc13783_ts_report_sample(priv); |
| 133 | } | 130 | } |
| 134 | 131 | ||
| @@ -137,21 +134,21 @@ static int mc13783_ts_open(struct input_dev *dev) | |||
| 137 | struct mc13783_ts_priv *priv = input_get_drvdata(dev); | 134 | struct mc13783_ts_priv *priv = input_get_drvdata(dev); |
| 138 | int ret; | 135 | int ret; |
| 139 | 136 | ||
| 140 | mc13xxx_lock(priv->mc13xxx); | 137 | mc13783_lock(priv->mc13783); |
| 141 | 138 | ||
| 142 | mc13xxx_irq_ack(priv->mc13xxx, MC13XXX_IRQ_TS); | 139 | mc13783_irq_ack(priv->mc13783, MC13783_IRQ_TS); |
| 143 | 140 | ||
| 144 | ret = mc13xxx_irq_request(priv->mc13xxx, MC13XXX_IRQ_TS, | 141 | ret = mc13783_irq_request(priv->mc13783, MC13783_IRQ_TS, |
| 145 | mc13783_ts_handler, MC13783_TS_NAME, priv); | 142 | mc13783_ts_handler, MC13783_TS_NAME, priv); |
| 146 | if (ret) | 143 | if (ret) |
| 147 | goto out; | 144 | goto out; |
| 148 | 145 | ||
| 149 | ret = mc13xxx_reg_rmw(priv->mc13xxx, MC13XXX_ADC0, | 146 | ret = mc13783_reg_rmw(priv->mc13783, MC13783_ADC0, |
| 150 | MC13XXX_ADC0_TSMOD_MASK, MC13XXX_ADC0_TSMOD0); | 147 | MC13783_ADC0_TSMOD_MASK, MC13783_ADC0_TSMOD0); |
| 151 | if (ret) | 148 | if (ret) |
| 152 | mc13xxx_irq_free(priv->mc13xxx, MC13XXX_IRQ_TS, priv); | 149 | mc13783_irq_free(priv->mc13783, MC13783_IRQ_TS, priv); |
| 153 | out: | 150 | out: |
| 154 | mc13xxx_unlock(priv->mc13xxx); | 151 | mc13783_unlock(priv->mc13783); |
| 155 | return ret; | 152 | return ret; |
| 156 | } | 153 | } |
| 157 | 154 | ||
| @@ -159,11 +156,11 @@ static void mc13783_ts_close(struct input_dev *dev) | |||
| 159 | { | 156 | { |
| 160 | struct mc13783_ts_priv *priv = input_get_drvdata(dev); | 157 | struct mc13783_ts_priv *priv = input_get_drvdata(dev); |
| 161 | 158 | ||
| 162 | mc13xxx_lock(priv->mc13xxx); | 159 | mc13783_lock(priv->mc13783); |
| 163 | mc13xxx_reg_rmw(priv->mc13xxx, MC13XXX_ADC0, | 160 | mc13783_reg_rmw(priv->mc13783, MC13783_ADC0, |
| 164 | MC13XXX_ADC0_TSMOD_MASK, 0); | 161 | MC13783_ADC0_TSMOD_MASK, 0); |
| 165 | mc13xxx_irq_free(priv->mc13xxx, MC13XXX_IRQ_TS, priv); | 162 | mc13783_irq_free(priv->mc13783, MC13783_IRQ_TS, priv); |
| 166 | mc13xxx_unlock(priv->mc13xxx); | 163 | mc13783_unlock(priv->mc13783); |
| 167 | 164 | ||
| 168 | cancel_delayed_work_sync(&priv->work); | 165 | cancel_delayed_work_sync(&priv->work); |
| 169 | } | 166 | } |
| @@ -180,14 +177,8 @@ static int __init mc13783_ts_probe(struct platform_device *pdev) | |||
| 180 | goto err_free_mem; | 177 | goto err_free_mem; |
| 181 | 178 | ||
| 182 | INIT_DELAYED_WORK(&priv->work, mc13783_ts_work); | 179 | INIT_DELAYED_WORK(&priv->work, mc13783_ts_work); |
| 183 | priv->mc13xxx = dev_get_drvdata(pdev->dev.parent); | 180 | priv->mc13783 = dev_get_drvdata(pdev->dev.parent); |
| 184 | priv->idev = idev; | 181 | priv->idev = idev; |
| 185 | priv->touch = dev_get_platdata(&pdev->dev); | ||
| 186 | if (!priv->touch) { | ||
| 187 | dev_err(&pdev->dev, "missing platform data\n"); | ||
| 188 | ret = -ENODEV; | ||
| 189 | goto err_free_mem; | ||
| 190 | } | ||
| 191 | 182 | ||
| 192 | /* | 183 | /* |
| 193 | * We need separate workqueue because mc13783_adc_do_conversion | 184 | * We need separate workqueue because mc13783_adc_do_conversion |
| @@ -229,7 +220,7 @@ err_free_mem: | |||
| 229 | return ret; | 220 | return ret; |
| 230 | } | 221 | } |
| 231 | 222 | ||
| 232 | static int mc13783_ts_remove(struct platform_device *pdev) | 223 | static int __devexit mc13783_ts_remove(struct platform_device *pdev) |
| 233 | { | 224 | { |
| 234 | struct mc13783_ts_priv *priv = platform_get_drvdata(pdev); | 225 | struct mc13783_ts_priv *priv = platform_get_drvdata(pdev); |
| 235 | 226 | ||
| @@ -243,7 +234,7 @@ static int mc13783_ts_remove(struct platform_device *pdev) | |||
| 243 | } | 234 | } |
| 244 | 235 | ||
| 245 | static struct platform_driver mc13783_ts_driver = { | 236 | static struct platform_driver mc13783_ts_driver = { |
| 246 | .remove = mc13783_ts_remove, | 237 | .remove = __devexit_p(mc13783_ts_remove), |
| 247 | .driver = { | 238 | .driver = { |
| 248 | .owner = THIS_MODULE, | 239 | .owner = THIS_MODULE, |
| 249 | .name = MC13783_TS_NAME, | 240 | .name = MC13783_TS_NAME, |
diff --git a/drivers/input/touchscreen/mcs5000_ts.c b/drivers/input/touchscreen/mcs5000_ts.c index f9f4e0c56ed..2d84c80ceb6 100644 --- a/drivers/input/touchscreen/mcs5000_ts.c +++ b/drivers/input/touchscreen/mcs5000_ts.c | |||
| @@ -187,7 +187,7 @@ static void mcs5000_ts_phys_init(struct mcs5000_ts_data *data) | |||
| 187 | OP_MODE_ACTIVE | REPORT_RATE_80); | 187 | OP_MODE_ACTIVE | REPORT_RATE_80); |
| 188 | } | 188 | } |
| 189 | 189 | ||
| 190 | static int mcs5000_ts_probe(struct i2c_client *client, | 190 | static int __devinit mcs5000_ts_probe(struct i2c_client *client, |
| 191 | const struct i2c_device_id *id) | 191 | const struct i2c_device_id *id) |
| 192 | { | 192 | { |
| 193 | struct mcs5000_ts_data *data; | 193 | struct mcs5000_ts_data *data; |
| @@ -249,7 +249,7 @@ err_free_mem: | |||
| 249 | return ret; | 249 | return ret; |
| 250 | } | 250 | } |
| 251 | 251 | ||
| 252 | static int mcs5000_ts_remove(struct i2c_client *client) | 252 | static int __devexit mcs5000_ts_remove(struct i2c_client *client) |
| 253 | { | 253 | { |
| 254 | struct mcs5000_ts_data *data = i2c_get_clientdata(client); | 254 | struct mcs5000_ts_data *data = i2c_get_clientdata(client); |
| 255 | 255 | ||
| @@ -292,7 +292,7 @@ MODULE_DEVICE_TABLE(i2c, mcs5000_ts_id); | |||
| 292 | 292 | ||
| 293 | static struct i2c_driver mcs5000_ts_driver = { | 293 | static struct i2c_driver mcs5000_ts_driver = { |
| 294 | .probe = mcs5000_ts_probe, | 294 | .probe = mcs5000_ts_probe, |
| 295 | .remove = mcs5000_ts_remove, | 295 | .remove = __devexit_p(mcs5000_ts_remove), |
| 296 | .driver = { | 296 | .driver = { |
| 297 | .name = "mcs5000_ts", | 297 | .name = "mcs5000_ts", |
| 298 | #ifdef CONFIG_PM | 298 | #ifdef CONFIG_PM |
| @@ -302,7 +302,18 @@ static struct i2c_driver mcs5000_ts_driver = { | |||
| 302 | .id_table = mcs5000_ts_id, | 302 | .id_table = mcs5000_ts_id, |
| 303 | }; | 303 | }; |
| 304 | 304 | ||
| 305 | module_i2c_driver(mcs5000_ts_driver); | 305 | static int __init mcs5000_ts_init(void) |
| 306 | { | ||
| 307 | return i2c_add_driver(&mcs5000_ts_driver); | ||
| 308 | } | ||
| 309 | |||
| 310 | static void __exit mcs5000_ts_exit(void) | ||
| 311 | { | ||
| 312 | i2c_del_driver(&mcs5000_ts_driver); | ||
| 313 | } | ||
| 314 | |||
| 315 | module_init(mcs5000_ts_init); | ||
| 316 | module_exit(mcs5000_ts_exit); | ||
| 306 | 317 | ||
| 307 | /* Module information */ | 318 | /* Module information */ |
| 308 | MODULE_AUTHOR("Joonyoung Shim <jy0922.shim@samsung.com>"); | 319 | MODULE_AUTHOR("Joonyoung Shim <jy0922.shim@samsung.com>"); |
diff --git a/drivers/input/touchscreen/migor_ts.c b/drivers/input/touchscreen/migor_ts.c index c038db93e2c..5803bd0c1cc 100644 --- a/drivers/input/touchscreen/migor_ts.c +++ b/drivers/input/touchscreen/migor_ts.c | |||
| @@ -36,6 +36,7 @@ | |||
| 36 | struct migor_ts_priv { | 36 | struct migor_ts_priv { |
| 37 | struct i2c_client *client; | 37 | struct i2c_client *client; |
| 38 | struct input_dev *input; | 38 | struct input_dev *input; |
| 39 | struct delayed_work work; | ||
| 39 | int irq; | 40 | int irq; |
| 40 | }; | 41 | }; |
| 41 | 42 | ||
| @@ -43,24 +44,15 @@ static const u_int8_t migor_ts_ena_seq[17] = { 0x33, 0x22, 0x11, | |||
| 43 | 0x01, 0x06, 0x07, }; | 44 | 0x01, 0x06, 0x07, }; |
| 44 | static const u_int8_t migor_ts_dis_seq[17] = { }; | 45 | static const u_int8_t migor_ts_dis_seq[17] = { }; |
| 45 | 46 | ||
| 46 | static irqreturn_t migor_ts_isr(int irq, void *dev_id) | 47 | static void migor_ts_poscheck(struct work_struct *work) |
| 47 | { | 48 | { |
| 48 | struct migor_ts_priv *priv = dev_id; | 49 | struct migor_ts_priv *priv = container_of(work, |
| 50 | struct migor_ts_priv, | ||
| 51 | work.work); | ||
| 49 | unsigned short xpos, ypos; | 52 | unsigned short xpos, ypos; |
| 50 | unsigned char event; | 53 | unsigned char event; |
| 51 | u_int8_t buf[16]; | 54 | u_int8_t buf[16]; |
| 52 | 55 | ||
| 53 | /* | ||
| 54 | * The touch screen controller chip is hooked up to the CPU | ||
| 55 | * using I2C and a single interrupt line. The interrupt line | ||
| 56 | * is pulled low whenever someone taps the screen. To deassert | ||
| 57 | * the interrupt line we need to acknowledge the interrupt by | ||
| 58 | * communicating with the controller over the slow i2c bus. | ||
| 59 | * | ||
| 60 | * Since I2C bus controller may sleep we are using threaded | ||
| 61 | * IRQ here. | ||
| 62 | */ | ||
| 63 | |||
| 64 | memset(buf, 0, sizeof(buf)); | 56 | memset(buf, 0, sizeof(buf)); |
| 65 | 57 | ||
| 66 | /* Set Index 0 */ | 58 | /* Set Index 0 */ |
| @@ -80,25 +72,41 @@ static irqreturn_t migor_ts_isr(int irq, void *dev_id) | |||
| 80 | xpos = ((buf[11] & 0x03) << 8 | buf[10]); | 72 | xpos = ((buf[11] & 0x03) << 8 | buf[10]); |
| 81 | event = buf[12]; | 73 | event = buf[12]; |
| 82 | 74 | ||
| 83 | switch (event) { | 75 | if (event == EVENT_PENDOWN || event == EVENT_REPEAT) { |
| 84 | case EVENT_PENDOWN: | ||
| 85 | case EVENT_REPEAT: | ||
| 86 | input_report_key(priv->input, BTN_TOUCH, 1); | 76 | input_report_key(priv->input, BTN_TOUCH, 1); |
| 87 | input_report_abs(priv->input, ABS_X, ypos); /*X-Y swap*/ | 77 | input_report_abs(priv->input, ABS_X, ypos); /*X-Y swap*/ |
| 88 | input_report_abs(priv->input, ABS_Y, xpos); | 78 | input_report_abs(priv->input, ABS_Y, xpos); |
| 89 | input_sync(priv->input); | 79 | input_sync(priv->input); |
| 90 | break; | 80 | } else if (event == EVENT_PENUP) { |
| 91 | |||
| 92 | case EVENT_PENUP: | ||
| 93 | input_report_key(priv->input, BTN_TOUCH, 0); | 81 | input_report_key(priv->input, BTN_TOUCH, 0); |
| 94 | input_sync(priv->input); | 82 | input_sync(priv->input); |
| 95 | break; | ||
| 96 | } | 83 | } |
| 97 | |||
| 98 | out: | 84 | out: |
| 85 | enable_irq(priv->irq); | ||
| 86 | } | ||
| 87 | |||
| 88 | static irqreturn_t migor_ts_isr(int irq, void *dev_id) | ||
| 89 | { | ||
| 90 | struct migor_ts_priv *priv = dev_id; | ||
| 91 | |||
| 92 | /* the touch screen controller chip is hooked up to the cpu | ||
| 93 | * using i2c and a single interrupt line. the interrupt line | ||
| 94 | * is pulled low whenever someone taps the screen. to deassert | ||
| 95 | * the interrupt line we need to acknowledge the interrupt by | ||
| 96 | * communicating with the controller over the slow i2c bus. | ||
| 97 | * | ||
| 98 | * we can't acknowledge from interrupt context since the i2c | ||
| 99 | * bus controller may sleep, so we just disable the interrupt | ||
| 100 | * here and handle the acknowledge using delayed work. | ||
| 101 | */ | ||
| 102 | |||
| 103 | disable_irq_nosync(irq); | ||
| 104 | schedule_delayed_work(&priv->work, HZ / 20); | ||
| 105 | |||
| 99 | return IRQ_HANDLED; | 106 | return IRQ_HANDLED; |
| 100 | } | 107 | } |
| 101 | 108 | ||
| 109 | |||
| 102 | static int migor_ts_open(struct input_dev *dev) | 110 | static int migor_ts_open(struct input_dev *dev) |
| 103 | { | 111 | { |
| 104 | struct migor_ts_priv *priv = input_get_drvdata(dev); | 112 | struct migor_ts_priv *priv = input_get_drvdata(dev); |
| @@ -123,6 +131,15 @@ static void migor_ts_close(struct input_dev *dev) | |||
| 123 | 131 | ||
| 124 | disable_irq(priv->irq); | 132 | disable_irq(priv->irq); |
| 125 | 133 | ||
| 134 | /* cancel pending work and wait for migor_ts_poscheck() to finish */ | ||
| 135 | if (cancel_delayed_work_sync(&priv->work)) { | ||
| 136 | /* | ||
| 137 | * if migor_ts_poscheck was canceled we need to enable IRQ | ||
| 138 | * here to balance disable done in migor_ts_isr. | ||
| 139 | */ | ||
| 140 | enable_irq(priv->irq); | ||
| 141 | } | ||
| 142 | |||
| 126 | /* disable controller */ | 143 | /* disable controller */ |
| 127 | i2c_master_send(client, migor_ts_dis_seq, sizeof(migor_ts_dis_seq)); | 144 | i2c_master_send(client, migor_ts_dis_seq, sizeof(migor_ts_dis_seq)); |
| 128 | 145 | ||
| @@ -137,20 +154,23 @@ static int migor_ts_probe(struct i2c_client *client, | |||
| 137 | int error; | 154 | int error; |
| 138 | 155 | ||
| 139 | priv = kzalloc(sizeof(*priv), GFP_KERNEL); | 156 | priv = kzalloc(sizeof(*priv), GFP_KERNEL); |
| 140 | input = input_allocate_device(); | 157 | if (!priv) { |
| 141 | if (!priv || !input) { | 158 | dev_err(&client->dev, "failed to allocate driver data\n"); |
| 142 | dev_err(&client->dev, "failed to allocate memory\n"); | ||
| 143 | error = -ENOMEM; | 159 | error = -ENOMEM; |
| 144 | goto err_free_mem; | 160 | goto err0; |
| 145 | } | 161 | } |
| 146 | 162 | ||
| 147 | priv->client = client; | 163 | dev_set_drvdata(&client->dev, priv); |
| 148 | priv->input = input; | ||
| 149 | priv->irq = client->irq; | ||
| 150 | 164 | ||
| 151 | input->evbit[0] = BIT_MASK(EV_KEY) | BIT_MASK(EV_ABS); | 165 | input = input_allocate_device(); |
| 166 | if (!input) { | ||
| 167 | dev_err(&client->dev, "Failed to allocate input device.\n"); | ||
| 168 | error = -ENOMEM; | ||
| 169 | goto err1; | ||
| 170 | } | ||
| 152 | 171 | ||
| 153 | __set_bit(BTN_TOUCH, input->keybit); | 172 | input->evbit[0] = BIT_MASK(EV_KEY) | BIT_MASK(EV_ABS); |
| 173 | input->keybit[BIT_WORD(BTN_TOUCH)] = BIT_MASK(BTN_TOUCH); | ||
| 154 | 174 | ||
| 155 | input_set_abs_params(input, ABS_X, 95, 955, 0, 0); | 175 | input_set_abs_params(input, ABS_X, 95, 955, 0, 0); |
| 156 | input_set_abs_params(input, ABS_Y, 85, 935, 0, 0); | 176 | input_set_abs_params(input, ABS_Y, 85, 935, 0, 0); |
| @@ -164,34 +184,39 @@ static int migor_ts_probe(struct i2c_client *client, | |||
| 164 | 184 | ||
| 165 | input_set_drvdata(input, priv); | 185 | input_set_drvdata(input, priv); |
| 166 | 186 | ||
| 167 | error = request_threaded_irq(priv->irq, NULL, migor_ts_isr, | 187 | priv->client = client; |
| 168 | IRQF_TRIGGER_LOW | IRQF_ONESHOT, | 188 | priv->input = input; |
| 169 | client->name, priv); | 189 | INIT_DELAYED_WORK(&priv->work, migor_ts_poscheck); |
| 170 | if (error) { | 190 | priv->irq = client->irq; |
| 171 | dev_err(&client->dev, "Unable to request touchscreen IRQ.\n"); | ||
| 172 | goto err_free_mem; | ||
| 173 | } | ||
| 174 | 191 | ||
| 175 | error = input_register_device(input); | 192 | error = input_register_device(input); |
| 176 | if (error) | 193 | if (error) |
| 177 | goto err_free_irq; | 194 | goto err1; |
| 178 | 195 | ||
| 179 | i2c_set_clientdata(client, priv); | 196 | error = request_irq(priv->irq, migor_ts_isr, IRQF_TRIGGER_LOW, |
| 180 | device_init_wakeup(&client->dev, 1); | 197 | client->name, priv); |
| 198 | if (error) { | ||
| 199 | dev_err(&client->dev, "Unable to request touchscreen IRQ.\n"); | ||
| 200 | goto err2; | ||
| 201 | } | ||
| 181 | 202 | ||
| 203 | device_init_wakeup(&client->dev, 1); | ||
| 182 | return 0; | 204 | return 0; |
| 183 | 205 | ||
| 184 | err_free_irq: | 206 | err2: |
| 185 | free_irq(priv->irq, priv); | 207 | input_unregister_device(input); |
| 186 | err_free_mem: | 208 | input = NULL; /* so we dont try to free it below */ |
| 209 | err1: | ||
| 187 | input_free_device(input); | 210 | input_free_device(input); |
| 188 | kfree(priv); | 211 | kfree(priv); |
| 212 | err0: | ||
| 213 | dev_set_drvdata(&client->dev, NULL); | ||
| 189 | return error; | 214 | return error; |
| 190 | } | 215 | } |
| 191 | 216 | ||
| 192 | static int migor_ts_remove(struct i2c_client *client) | 217 | static int migor_ts_remove(struct i2c_client *client) |
| 193 | { | 218 | { |
| 194 | struct migor_ts_priv *priv = i2c_get_clientdata(client); | 219 | struct migor_ts_priv *priv = dev_get_drvdata(&client->dev); |
| 195 | 220 | ||
| 196 | free_irq(priv->irq, priv); | 221 | free_irq(priv->irq, priv); |
| 197 | input_unregister_device(priv->input); | 222 | input_unregister_device(priv->input); |
| @@ -205,7 +230,7 @@ static int migor_ts_remove(struct i2c_client *client) | |||
| 205 | static int migor_ts_suspend(struct device *dev) | 230 | static int migor_ts_suspend(struct device *dev) |
| 206 | { | 231 | { |
| 207 | struct i2c_client *client = to_i2c_client(dev); | 232 | struct i2c_client *client = to_i2c_client(dev); |
| 208 | struct migor_ts_priv *priv = i2c_get_clientdata(client); | 233 | struct migor_ts_priv *priv = dev_get_drvdata(&client->dev); |
| 209 | 234 | ||
| 210 | if (device_may_wakeup(&client->dev)) | 235 | if (device_may_wakeup(&client->dev)) |
| 211 | enable_irq_wake(priv->irq); | 236 | enable_irq_wake(priv->irq); |
| @@ -216,7 +241,7 @@ static int migor_ts_suspend(struct device *dev) | |||
| 216 | static int migor_ts_resume(struct device *dev) | 241 | static int migor_ts_resume(struct device *dev) |
| 217 | { | 242 | { |
| 218 | struct i2c_client *client = to_i2c_client(dev); | 243 | struct i2c_client *client = to_i2c_client(dev); |
| 219 | struct migor_ts_priv *priv = i2c_get_clientdata(client); | 244 | struct migor_ts_priv *priv = dev_get_drvdata(&client->dev); |
| 220 | 245 | ||
| 221 | if (device_may_wakeup(&client->dev)) | 246 | if (device_may_wakeup(&client->dev)) |
| 222 | disable_irq_wake(priv->irq); | 247 | disable_irq_wake(priv->irq); |
| @@ -242,8 +267,19 @@ static struct i2c_driver migor_ts_driver = { | |||
| 242 | .id_table = migor_ts_id, | 267 | .id_table = migor_ts_id, |
| 243 | }; | 268 | }; |
| 244 | 269 | ||
| 245 | module_i2c_driver(migor_ts_driver); | 270 | static int __init migor_ts_init(void) |
| 271 | { | ||
| 272 | return i2c_add_driver(&migor_ts_driver); | ||
| 273 | } | ||
| 274 | |||
| 275 | static void __exit migor_ts_exit(void) | ||
| 276 | { | ||
| 277 | i2c_del_driver(&migor_ts_driver); | ||
| 278 | } | ||
| 246 | 279 | ||
| 247 | MODULE_DESCRIPTION("MigoR Touchscreen driver"); | 280 | MODULE_DESCRIPTION("MigoR Touchscreen driver"); |
| 248 | MODULE_AUTHOR("Magnus Damm <damm@opensource.se>"); | 281 | MODULE_AUTHOR("Magnus Damm <damm@opensource.se>"); |
| 249 | MODULE_LICENSE("GPL"); | 282 | MODULE_LICENSE("GPL"); |
| 283 | |||
| 284 | module_init(migor_ts_init); | ||
| 285 | module_exit(migor_ts_exit); | ||
diff --git a/drivers/input/touchscreen/mms114.c b/drivers/input/touchscreen/mms114.c deleted file mode 100644 index 98841d8aa63..00000000000 --- a/drivers/input/touchscreen/mms114.c +++ /dev/null | |||
| @@ -1,602 +0,0 @@ | |||
| 1 | /* | ||
| 2 | * Copyright (C) 2012 Samsung Electronics Co.Ltd | ||
| 3 | * Author: Joonyoung Shim <jy0922.shim@samsung.com> | ||
| 4 | * | ||
| 5 | * This program is free software; you can redistribute it and/or modify | ||
| 6 | * it under the terms of the GNU General Public License version 2 as | ||
| 7 | * published by the Free Software Foundation. | ||
| 8 | */ | ||
| 9 | |||
| 10 | #include <linux/module.h> | ||
| 11 | #include <linux/init.h> | ||
| 12 | #include <linux/delay.h> | ||
| 13 | #include <linux/of.h> | ||
| 14 | #include <linux/i2c.h> | ||
| 15 | #include <linux/i2c/mms114.h> | ||
| 16 | #include <linux/input/mt.h> | ||
| 17 | #include <linux/interrupt.h> | ||
| 18 | #include <linux/regulator/consumer.h> | ||
| 19 | #include <linux/slab.h> | ||
| 20 | |||
| 21 | /* Write only registers */ | ||
| 22 | #define MMS114_MODE_CONTROL 0x01 | ||
| 23 | #define MMS114_OPERATION_MODE_MASK 0xE | ||
| 24 | #define MMS114_ACTIVE (1 << 1) | ||
| 25 | |||
| 26 | #define MMS114_XY_RESOLUTION_H 0x02 | ||
| 27 | #define MMS114_X_RESOLUTION 0x03 | ||
| 28 | #define MMS114_Y_RESOLUTION 0x04 | ||
| 29 | #define MMS114_CONTACT_THRESHOLD 0x05 | ||
| 30 | #define MMS114_MOVING_THRESHOLD 0x06 | ||
| 31 | |||
| 32 | /* Read only registers */ | ||
| 33 | #define MMS114_PACKET_SIZE 0x0F | ||
| 34 | #define MMS114_INFOMATION 0x10 | ||
| 35 | #define MMS114_TSP_REV 0xF0 | ||
| 36 | |||
| 37 | /* Minimum delay time is 50us between stop and start signal of i2c */ | ||
| 38 | #define MMS114_I2C_DELAY 50 | ||
| 39 | |||
| 40 | /* 200ms needs after power on */ | ||
| 41 | #define MMS114_POWERON_DELAY 200 | ||
| 42 | |||
| 43 | /* Touchscreen absolute values */ | ||
| 44 | #define MMS114_MAX_AREA 0xff | ||
| 45 | |||
| 46 | #define MMS114_MAX_TOUCH 10 | ||
| 47 | #define MMS114_PACKET_NUM 8 | ||
| 48 | |||
| 49 | /* Touch type */ | ||
| 50 | #define MMS114_TYPE_NONE 0 | ||
| 51 | #define MMS114_TYPE_TOUCHSCREEN 1 | ||
| 52 | #define MMS114_TYPE_TOUCHKEY 2 | ||
| 53 | |||
| 54 | struct mms114_data { | ||
| 55 | struct i2c_client *client; | ||
| 56 | struct input_dev *input_dev; | ||
| 57 | struct regulator *core_reg; | ||
| 58 | struct regulator *io_reg; | ||
| 59 | const struct mms114_platform_data *pdata; | ||
| 60 | |||
| 61 | /* Use cache data for mode control register(write only) */ | ||
| 62 | u8 cache_mode_control; | ||
| 63 | }; | ||
| 64 | |||
| 65 | struct mms114_touch { | ||
| 66 | u8 id:4, reserved_bit4:1, type:2, pressed:1; | ||
| 67 | u8 x_hi:4, y_hi:4; | ||
| 68 | u8 x_lo; | ||
| 69 | u8 y_lo; | ||
| 70 | u8 width; | ||
| 71 | u8 strength; | ||
| 72 | u8 reserved[2]; | ||
| 73 | } __packed; | ||
| 74 | |||
| 75 | static int __mms114_read_reg(struct mms114_data *data, unsigned int reg, | ||
| 76 | unsigned int len, u8 *val) | ||
| 77 | { | ||
| 78 | struct i2c_client *client = data->client; | ||
| 79 | struct i2c_msg xfer[2]; | ||
| 80 | u8 buf = reg & 0xff; | ||
| 81 | int error; | ||
| 82 | |||
| 83 | if (reg <= MMS114_MODE_CONTROL && reg + len > MMS114_MODE_CONTROL) | ||
| 84 | BUG(); | ||
| 85 | |||
| 86 | /* Write register: use repeated start */ | ||
| 87 | xfer[0].addr = client->addr; | ||
| 88 | xfer[0].flags = I2C_M_TEN | I2C_M_NOSTART; | ||
| 89 | xfer[0].len = 1; | ||
| 90 | xfer[0].buf = &buf; | ||
| 91 | |||
| 92 | /* Read data */ | ||
| 93 | xfer[1].addr = client->addr; | ||
| 94 | xfer[1].flags = I2C_M_RD; | ||
| 95 | xfer[1].len = len; | ||
| 96 | xfer[1].buf = val; | ||
| 97 | |||
| 98 | error = i2c_transfer(client->adapter, xfer, 2); | ||
| 99 | if (error != 2) { | ||
| 100 | dev_err(&client->dev, | ||
| 101 | "%s: i2c transfer failed (%d)\n", __func__, error); | ||
| 102 | return error < 0 ? error : -EIO; | ||
| 103 | } | ||
| 104 | udelay(MMS114_I2C_DELAY); | ||
| 105 | |||
| 106 | return 0; | ||
| 107 | } | ||
| 108 | |||
| 109 | static int mms114_read_reg(struct mms114_data *data, unsigned int reg) | ||
| 110 | { | ||
| 111 | u8 val; | ||
| 112 | int error; | ||
| 113 | |||
| 114 | if (reg == MMS114_MODE_CONTROL) | ||
| 115 | return data->cache_mode_control; | ||
| 116 | |||
| 117 | error = __mms114_read_reg(data, reg, 1, &val); | ||
| 118 | return error < 0 ? error : val; | ||
| 119 | } | ||
| 120 | |||
| 121 | static int mms114_write_reg(struct mms114_data *data, unsigned int reg, | ||
| 122 | unsigned int val) | ||
| 123 | { | ||
| 124 | struct i2c_client *client = data->client; | ||
| 125 | u8 buf[2]; | ||
| 126 | int error; | ||
| 127 | |||
| 128 | buf[0] = reg & 0xff; | ||
| 129 | buf[1] = val & 0xff; | ||
| 130 | |||
| 131 | error = i2c_master_send(client, buf, 2); | ||
| 132 | if (error != 2) { | ||
| 133 | dev_err(&client->dev, | ||
| 134 | "%s: i2c send failed (%d)\n", __func__, error); | ||
| 135 | return error < 0 ? error : -EIO; | ||
| 136 | } | ||
| 137 | udelay(MMS114_I2C_DELAY); | ||
| 138 | |||
| 139 | if (reg == MMS114_MODE_CONTROL) | ||
| 140 | data->cache_mode_control = val; | ||
| 141 | |||
| 142 | return 0; | ||
| 143 | } | ||
| 144 | |||
| 145 | static void mms114_process_mt(struct mms114_data *data, struct mms114_touch *touch) | ||
| 146 | { | ||
| 147 | const struct mms114_platform_data *pdata = data->pdata; | ||
| 148 | struct i2c_client *client = data->client; | ||
| 149 | struct input_dev *input_dev = data->input_dev; | ||
| 150 | unsigned int id; | ||
| 151 | unsigned int x; | ||
| 152 | unsigned int y; | ||
| 153 | |||
| 154 | if (touch->id > MMS114_MAX_TOUCH) { | ||
| 155 | dev_err(&client->dev, "Wrong touch id (%d)\n", touch->id); | ||
| 156 | return; | ||
| 157 | } | ||
| 158 | |||
| 159 | if (touch->type != MMS114_TYPE_TOUCHSCREEN) { | ||
| 160 | dev_err(&client->dev, "Wrong touch type (%d)\n", touch->type); | ||
| 161 | return; | ||
| 162 | } | ||
| 163 | |||
| 164 | id = touch->id - 1; | ||
| 165 | x = touch->x_lo | touch->x_hi << 8; | ||
| 166 | y = touch->y_lo | touch->y_hi << 8; | ||
| 167 | if (x > pdata->x_size || y > pdata->y_size) { | ||
| 168 | dev_dbg(&client->dev, | ||
| 169 | "Wrong touch coordinates (%d, %d)\n", x, y); | ||
| 170 | return; | ||
| 171 | } | ||
| 172 | |||
| 173 | if (pdata->x_invert) | ||
| 174 | x = pdata->x_size - x; | ||
| 175 | if (pdata->y_invert) | ||
| 176 | y = pdata->y_size - y; | ||
| 177 | |||
| 178 | dev_dbg(&client->dev, | ||
| 179 | "id: %d, type: %d, pressed: %d, x: %d, y: %d, width: %d, strength: %d\n", | ||
| 180 | id, touch->type, touch->pressed, | ||
| 181 | x, y, touch->width, touch->strength); | ||
| 182 | |||
| 183 | input_mt_slot(input_dev, id); | ||
| 184 | input_mt_report_slot_state(input_dev, MT_TOOL_FINGER, touch->pressed); | ||
| 185 | |||
| 186 | if (touch->pressed) { | ||
| 187 | input_report_abs(input_dev, ABS_MT_TOUCH_MAJOR, touch->width); | ||
| 188 | input_report_abs(input_dev, ABS_MT_POSITION_X, x); | ||
| 189 | input_report_abs(input_dev, ABS_MT_POSITION_Y, y); | ||
| 190 | input_report_abs(input_dev, ABS_MT_PRESSURE, touch->strength); | ||
| 191 | } | ||
| 192 | } | ||
| 193 | |||
| 194 | static irqreturn_t mms114_interrupt(int irq, void *dev_id) | ||
| 195 | { | ||
| 196 | struct mms114_data *data = dev_id; | ||
| 197 | struct input_dev *input_dev = data->input_dev; | ||
| 198 | struct mms114_touch touch[MMS114_MAX_TOUCH]; | ||
| 199 | int packet_size; | ||
| 200 | int touch_size; | ||
| 201 | int index; | ||
| 202 | int error; | ||
| 203 | |||
| 204 | mutex_lock(&input_dev->mutex); | ||
| 205 | if (!input_dev->users) { | ||
| 206 | mutex_unlock(&input_dev->mutex); | ||
| 207 | goto out; | ||
| 208 | } | ||
| 209 | mutex_unlock(&input_dev->mutex); | ||
| 210 | |||
| 211 | packet_size = mms114_read_reg(data, MMS114_PACKET_SIZE); | ||
| 212 | if (packet_size <= 0) | ||
| 213 | goto out; | ||
| 214 | |||
| 215 | touch_size = packet_size / MMS114_PACKET_NUM; | ||
| 216 | |||
| 217 | error = __mms114_read_reg(data, MMS114_INFOMATION, packet_size, | ||
| 218 | (u8 *)touch); | ||
| 219 | if (error < 0) | ||
| 220 | goto out; | ||
| 221 | |||
| 222 | for (index = 0; index < touch_size; index++) | ||
| 223 | mms114_process_mt(data, touch + index); | ||
| 224 | |||
| 225 | input_mt_report_pointer_emulation(data->input_dev, true); | ||
| 226 | input_sync(data->input_dev); | ||
| 227 | |||
| 228 | out: | ||
| 229 | return IRQ_HANDLED; | ||
| 230 | } | ||
| 231 | |||
| 232 | static int mms114_set_active(struct mms114_data *data, bool active) | ||
| 233 | { | ||
| 234 | int val; | ||
| 235 | |||
| 236 | val = mms114_read_reg(data, MMS114_MODE_CONTROL); | ||
| 237 | if (val < 0) | ||
| 238 | return val; | ||
| 239 | |||
| 240 | val &= ~MMS114_OPERATION_MODE_MASK; | ||
| 241 | |||
| 242 | /* If active is false, sleep mode */ | ||
| 243 | if (active) | ||
| 244 | val |= MMS114_ACTIVE; | ||
| 245 | |||
| 246 | return mms114_write_reg(data, MMS114_MODE_CONTROL, val); | ||
| 247 | } | ||
| 248 | |||
| 249 | static int mms114_get_version(struct mms114_data *data) | ||
| 250 | { | ||
| 251 | struct device *dev = &data->client->dev; | ||
| 252 | u8 buf[6]; | ||
| 253 | int error; | ||
| 254 | |||
| 255 | error = __mms114_read_reg(data, MMS114_TSP_REV, 6, buf); | ||
| 256 | if (error < 0) | ||
| 257 | return error; | ||
| 258 | |||
| 259 | dev_info(dev, "TSP Rev: 0x%x, HW Rev: 0x%x, Firmware Ver: 0x%x\n", | ||
| 260 | buf[0], buf[1], buf[3]); | ||
| 261 | |||
| 262 | return 0; | ||
| 263 | } | ||
| 264 | |||
| 265 | static int mms114_setup_regs(struct mms114_data *data) | ||
| 266 | { | ||
| 267 | const struct mms114_platform_data *pdata = data->pdata; | ||
| 268 | int val; | ||
| 269 | int error; | ||
| 270 | |||
| 271 | error = mms114_get_version(data); | ||
| 272 | if (error < 0) | ||
| 273 | return error; | ||
| 274 | |||
| 275 | error = mms114_set_active(data, true); | ||
| 276 | if (error < 0) | ||
| 277 | return error; | ||
| 278 | |||
| 279 | val = (pdata->x_size >> 8) & 0xf; | ||
| 280 | val |= ((pdata->y_size >> 8) & 0xf) << 4; | ||
| 281 | error = mms114_write_reg(data, MMS114_XY_RESOLUTION_H, val); | ||
| 282 | if (error < 0) | ||
| 283 | return error; | ||
| 284 | |||
| 285 | val = pdata->x_size & 0xff; | ||
| 286 | error = mms114_write_reg(data, MMS114_X_RESOLUTION, val); | ||
| 287 | if (error < 0) | ||
| 288 | return error; | ||
| 289 | |||
| 290 | val = pdata->y_size & 0xff; | ||
| 291 | error = mms114_write_reg(data, MMS114_Y_RESOLUTION, val); | ||
| 292 | if (error < 0) | ||
| 293 | return error; | ||
| 294 | |||
| 295 | if (pdata->contact_threshold) { | ||
| 296 | error = mms114_write_reg(data, MMS114_CONTACT_THRESHOLD, | ||
| 297 | pdata->contact_threshold); | ||
| 298 | if (error < 0) | ||
| 299 | return error; | ||
| 300 | } | ||
| 301 | |||
| 302 | if (pdata->moving_threshold) { | ||
| 303 | error = mms114_write_reg(data, MMS114_MOVING_THRESHOLD, | ||
| 304 | pdata->moving_threshold); | ||
| 305 | if (error < 0) | ||
| 306 | return error; | ||
| 307 | } | ||
| 308 | |||
| 309 | return 0; | ||
| 310 | } | ||
| 311 | |||
| 312 | static int mms114_start(struct mms114_data *data) | ||
| 313 | { | ||
| 314 | struct i2c_client *client = data->client; | ||
| 315 | int error; | ||
| 316 | |||
| 317 | if (data->core_reg) | ||
| 318 | regulator_enable(data->core_reg); | ||
| 319 | if (data->io_reg) | ||
| 320 | regulator_enable(data->io_reg); | ||
| 321 | mdelay(MMS114_POWERON_DELAY); | ||
| 322 | |||
| 323 | error = mms114_setup_regs(data); | ||
| 324 | if (error < 0) | ||
| 325 | return error; | ||
| 326 | |||
| 327 | if (data->pdata->cfg_pin) | ||
| 328 | data->pdata->cfg_pin(true); | ||
| 329 | |||
| 330 | enable_irq(client->irq); | ||
| 331 | |||
| 332 | return 0; | ||
| 333 | } | ||
| 334 | |||
| 335 | static void mms114_stop(struct mms114_data *data) | ||
| 336 | { | ||
| 337 | struct i2c_client *client = data->client; | ||
| 338 | |||
| 339 | disable_irq(client->irq); | ||
| 340 | |||
| 341 | if (data->pdata->cfg_pin) | ||
| 342 | data->pdata->cfg_pin(false); | ||
| 343 | |||
| 344 | if (data->io_reg) | ||
| 345 | regulator_disable(data->io_reg); | ||
| 346 | if (data->core_reg) | ||
| 347 | regulator_disable(data->core_reg); | ||
| 348 | } | ||
| 349 | |||
| 350 | static int mms114_input_open(struct input_dev *dev) | ||
| 351 | { | ||
| 352 | struct mms114_data *data = input_get_drvdata(dev); | ||
| 353 | |||
| 354 | return mms114_start(data); | ||
| 355 | } | ||
| 356 | |||
| 357 | static void mms114_input_close(struct input_dev *dev) | ||
| 358 | { | ||
| 359 | struct mms114_data *data = input_get_drvdata(dev); | ||
| 360 | |||
| 361 | mms114_stop(data); | ||
| 362 | } | ||
| 363 | |||
| 364 | #ifdef CONFIG_OF | ||
| 365 | static struct mms114_platform_data *mms114_parse_dt(struct device *dev) | ||
| 366 | { | ||
| 367 | struct mms114_platform_data *pdata; | ||
| 368 | struct device_node *np = dev->of_node; | ||
| 369 | |||
| 370 | if (!np) | ||
| 371 | return NULL; | ||
| 372 | |||
| 373 | pdata = devm_kzalloc(dev, sizeof(*pdata), GFP_KERNEL); | ||
| 374 | if (!pdata) { | ||
| 375 | dev_err(dev, "failed to allocate platform data\n"); | ||
| 376 | return NULL; | ||
| 377 | } | ||
| 378 | |||
| 379 | if (of_property_read_u32(np, "x-size", &pdata->x_size)) { | ||
| 380 | dev_err(dev, "failed to get x-size property\n"); | ||
| 381 | return NULL; | ||
| 382 | }; | ||
| 383 | |||
| 384 | if (of_property_read_u32(np, "y-size", &pdata->y_size)) { | ||
| 385 | dev_err(dev, "failed to get y-size property\n"); | ||
| 386 | return NULL; | ||
| 387 | }; | ||
| 388 | |||
| 389 | of_property_read_u32(np, "contact-threshold", | ||
| 390 | &pdata->contact_threshold); | ||
| 391 | of_property_read_u32(np, "moving-threshold", | ||
| 392 | &pdata->moving_threshold); | ||
| 393 | |||
| 394 | if (of_find_property(np, "x-invert", NULL)) | ||
| 395 | pdata->x_invert = true; | ||
| 396 | if (of_find_property(np, "y-invert", NULL)) | ||
| 397 | pdata->y_invert = true; | ||
| 398 | |||
| 399 | return pdata; | ||
| 400 | } | ||
| 401 | #else | ||
| 402 | static inline struct mms114_platform_data *mms114_parse_dt(struct device *dev) | ||
| 403 | { | ||
| 404 | return NULL; | ||
| 405 | } | ||
| 406 | #endif | ||
| 407 | |||
| 408 | static int mms114_probe(struct i2c_client *client, | ||
| 409 | const struct i2c_device_id *id) | ||
| 410 | { | ||
| 411 | const struct mms114_platform_data *pdata; | ||
| 412 | struct mms114_data *data; | ||
| 413 | struct input_dev *input_dev; | ||
| 414 | int error; | ||
| 415 | |||
| 416 | pdata = dev_get_platdata(&client->dev); | ||
| 417 | if (!pdata) | ||
| 418 | pdata = mms114_parse_dt(&client->dev); | ||
| 419 | |||
| 420 | if (!pdata) { | ||
| 421 | dev_err(&client->dev, "Need platform data\n"); | ||
| 422 | return -EINVAL; | ||
| 423 | } | ||
| 424 | |||
| 425 | if (!i2c_check_functionality(client->adapter, | ||
| 426 | I2C_FUNC_PROTOCOL_MANGLING)) { | ||
| 427 | dev_err(&client->dev, | ||
| 428 | "Need i2c bus that supports protocol mangling\n"); | ||
| 429 | return -ENODEV; | ||
| 430 | } | ||
| 431 | |||
| 432 | data = kzalloc(sizeof(struct mms114_data), GFP_KERNEL); | ||
| 433 | input_dev = input_allocate_device(); | ||
| 434 | if (!data || !input_dev) { | ||
| 435 | dev_err(&client->dev, "Failed to allocate memory\n"); | ||
| 436 | error = -ENOMEM; | ||
| 437 | goto err_free_mem; | ||
| 438 | } | ||
| 439 | |||
| 440 | data->client = client; | ||
| 441 | data->input_dev = input_dev; | ||
| 442 | data->pdata = pdata; | ||
| 443 | |||
| 444 | input_dev->name = "MELPAS MMS114 Touchscreen"; | ||
| 445 | input_dev->id.bustype = BUS_I2C; | ||
| 446 | input_dev->dev.parent = &client->dev; | ||
| 447 | input_dev->open = mms114_input_open; | ||
| 448 | input_dev->close = mms114_input_close; | ||
| 449 | |||
| 450 | __set_bit(EV_ABS, input_dev->evbit); | ||
| 451 | __set_bit(EV_KEY, input_dev->evbit); | ||
| 452 | __set_bit(BTN_TOUCH, input_dev->keybit); | ||
| 453 | input_set_abs_params(input_dev, ABS_X, 0, data->pdata->x_size, 0, 0); | ||
| 454 | input_set_abs_params(input_dev, ABS_Y, 0, data->pdata->y_size, 0, 0); | ||
| 455 | |||
| 456 | /* For multi touch */ | ||
| 457 | input_mt_init_slots(input_dev, MMS114_MAX_TOUCH, 0); | ||
| 458 | input_set_abs_params(input_dev, ABS_MT_TOUCH_MAJOR, | ||
| 459 | 0, MMS114_MAX_AREA, 0, 0); | ||
| 460 | input_set_abs_params(input_dev, ABS_MT_POSITION_X, | ||
| 461 | 0, data->pdata->x_size, 0, 0); | ||
| 462 | input_set_abs_params(input_dev, ABS_MT_POSITION_Y, | ||
| 463 | 0, data->pdata->y_size, 0, 0); | ||
| 464 | input_set_abs_params(input_dev, ABS_MT_PRESSURE, 0, 255, 0, 0); | ||
| 465 | |||
| 466 | input_set_drvdata(input_dev, data); | ||
| 467 | i2c_set_clientdata(client, data); | ||
| 468 | |||
| 469 | data->core_reg = regulator_get(&client->dev, "avdd"); | ||
| 470 | if (IS_ERR(data->core_reg)) { | ||
| 471 | error = PTR_ERR(data->core_reg); | ||
| 472 | dev_err(&client->dev, | ||
| 473 | "Unable to get the Core regulator (%d)\n", error); | ||
| 474 | goto err_free_mem; | ||
| 475 | } | ||
| 476 | |||
| 477 | data->io_reg = regulator_get(&client->dev, "vdd"); | ||
| 478 | if (IS_ERR(data->io_reg)) { | ||
| 479 | error = PTR_ERR(data->io_reg); | ||
| 480 | dev_err(&client->dev, | ||
| 481 | "Unable to get the IO regulator (%d)\n", error); | ||
| 482 | goto err_core_reg; | ||
| 483 | } | ||
| 484 | |||
| 485 | error = request_threaded_irq(client->irq, NULL, mms114_interrupt, | ||
| 486 | IRQF_TRIGGER_FALLING | IRQF_ONESHOT, "mms114", data); | ||
| 487 | if (error) { | ||
| 488 | dev_err(&client->dev, "Failed to register interrupt\n"); | ||
| 489 | goto err_io_reg; | ||
| 490 | } | ||
| 491 | disable_irq(client->irq); | ||
| 492 | |||
| 493 | error = input_register_device(data->input_dev); | ||
| 494 | if (error) | ||
| 495 | goto err_free_irq; | ||
| 496 | |||
| 497 | return 0; | ||
| 498 | |||
| 499 | err_free_irq: | ||
| 500 | free_irq(client->irq, data); | ||
| 501 | err_io_reg: | ||
| 502 | regulator_put(data->io_reg); | ||
| 503 | err_core_reg: | ||
| 504 | regulator_put(data->core_reg); | ||
| 505 | err_free_mem: | ||
| 506 | input_free_device(input_dev); | ||
| 507 | kfree(data); | ||
| 508 | return error; | ||
| 509 | } | ||
| 510 | |||
| 511 | static int mms114_remove(struct i2c_client *client) | ||
| 512 | { | ||
| 513 | struct mms114_data *data = i2c_get_clientdata(client); | ||
| 514 | |||
| 515 | free_irq(client->irq, data); | ||
| 516 | regulator_put(data->io_reg); | ||
| 517 | regulator_put(data->core_reg); | ||
| 518 | input_unregister_device(data->input_dev); | ||
| 519 | kfree(data); | ||
| 520 | |||
| 521 | return 0; | ||
| 522 | } | ||
| 523 | |||
| 524 | #ifdef CONFIG_PM_SLEEP | ||
| 525 | static int mms114_suspend(struct device *dev) | ||
| 526 | { | ||
| 527 | struct i2c_client *client = to_i2c_client(dev); | ||
| 528 | struct mms114_data *data = i2c_get_clientdata(client); | ||
| 529 | struct input_dev *input_dev = data->input_dev; | ||
| 530 | int id; | ||
| 531 | |||
| 532 | /* Release all touch */ | ||
| 533 | for (id = 0; id < MMS114_MAX_TOUCH; id++) { | ||
| 534 | input_mt_slot(input_dev, id); | ||
| 535 | input_mt_report_slot_state(input_dev, MT_TOOL_FINGER, false); | ||
| 536 | } | ||
| 537 | |||
| 538 | input_mt_report_pointer_emulation(input_dev, true); | ||
| 539 | input_sync(input_dev); | ||
| 540 | |||
| 541 | mutex_lock(&input_dev->mutex); | ||
| 542 | if (input_dev->users) | ||
| 543 | mms114_stop(data); | ||
| 544 | mutex_unlock(&input_dev->mutex); | ||
| 545 | |||
| 546 | return 0; | ||
| 547 | } | ||
| 548 | |||
| 549 | static int mms114_resume(struct device *dev) | ||
| 550 | { | ||
| 551 | struct i2c_client *client = to_i2c_client(dev); | ||
| 552 | struct mms114_data *data = i2c_get_clientdata(client); | ||
| 553 | struct input_dev *input_dev = data->input_dev; | ||
| 554 | int error; | ||
| 555 | |||
| 556 | mutex_lock(&input_dev->mutex); | ||
| 557 | if (input_dev->users) { | ||
| 558 | error = mms114_start(data); | ||
| 559 | if (error < 0) { | ||
| 560 | mutex_unlock(&input_dev->mutex); | ||
| 561 | return error; | ||
| 562 | } | ||
| 563 | } | ||
| 564 | mutex_unlock(&input_dev->mutex); | ||
| 565 | |||
| 566 | return 0; | ||
| 567 | } | ||
| 568 | #endif | ||
| 569 | |||
| 570 | static SIMPLE_DEV_PM_OPS(mms114_pm_ops, mms114_suspend, mms114_resume); | ||
| 571 | |||
| 572 | static const struct i2c_device_id mms114_id[] = { | ||
| 573 | { "mms114", 0 }, | ||
| 574 | { } | ||
| 575 | }; | ||
| 576 | MODULE_DEVICE_TABLE(i2c, mms114_id); | ||
| 577 | |||
| 578 | #ifdef CONFIG_OF | ||
| 579 | static struct of_device_id mms114_dt_match[] = { | ||
| 580 | { .compatible = "melfas,mms114" }, | ||
| 581 | { } | ||
| 582 | }; | ||
| 583 | #endif | ||
| 584 | |||
| 585 | static struct i2c_driver mms114_driver = { | ||
| 586 | .driver = { | ||
| 587 | .name = "mms114", | ||
| 588 | .owner = THIS_MODULE, | ||
| 589 | .pm = &mms114_pm_ops, | ||
| 590 | .of_match_table = of_match_ptr(mms114_dt_match), | ||
| 591 | }, | ||
| 592 | .probe = mms114_probe, | ||
| 593 | .remove = mms114_remove, | ||
| 594 | .id_table = mms114_id, | ||
| 595 | }; | ||
| 596 | |||
| 597 | module_i2c_driver(mms114_driver); | ||
| 598 | |||
| 599 | /* Module information */ | ||
| 600 | MODULE_AUTHOR("Joonyoung Shim <jy0922.shim@samsung.com>"); | ||
| 601 | MODULE_DESCRIPTION("MELFAS mms114 Touchscreen driver"); | ||
| 602 | MODULE_LICENSE("GPL"); | ||
diff --git a/drivers/input/touchscreen/mtouch.c b/drivers/input/touchscreen/mtouch.c index eb66b7c37c2..9077228418b 100644 --- a/drivers/input/touchscreen/mtouch.c +++ b/drivers/input/touchscreen/mtouch.c | |||
| @@ -202,4 +202,19 @@ static struct serio_driver mtouch_drv = { | |||
| 202 | .disconnect = mtouch_disconnect, | 202 | .disconnect = mtouch_disconnect, |
| 203 | }; | 203 | }; |
| 204 | 204 | ||
| 205 | module_serio_driver(mtouch_drv); | 205 | /* |
| 206 | * The functions for inserting/removing us as a module. | ||
| 207 | */ | ||
| 208 | |||
| 209 | static int __init mtouch_init(void) | ||
| 210 | { | ||
| 211 | return serio_register_driver(&mtouch_drv); | ||
| 212 | } | ||
| 213 | |||
| 214 | static void __exit mtouch_exit(void) | ||
| 215 | { | ||
| 216 | serio_unregister_driver(&mtouch_drv); | ||
| 217 | } | ||
| 218 | |||
| 219 | module_init(mtouch_init); | ||
| 220 | module_exit(mtouch_exit); | ||
diff --git a/drivers/input/touchscreen/pcap_ts.c b/drivers/input/touchscreen/pcap_ts.c index f22e04dd4e1..ea6ef16e59b 100644 --- a/drivers/input/touchscreen/pcap_ts.c +++ b/drivers/input/touchscreen/pcap_ts.c | |||
| @@ -137,7 +137,7 @@ static void pcap_ts_close(struct input_dev *dev) | |||
| 137 | pcap_ts->read_state << PCAP_ADC_TS_M_SHIFT); | 137 | pcap_ts->read_state << PCAP_ADC_TS_M_SHIFT); |
| 138 | } | 138 | } |
| 139 | 139 | ||
| 140 | static int pcap_ts_probe(struct platform_device *pdev) | 140 | static int __devinit pcap_ts_probe(struct platform_device *pdev) |
| 141 | { | 141 | { |
| 142 | struct input_dev *input_dev; | 142 | struct input_dev *input_dev; |
| 143 | struct pcap_ts *pcap_ts; | 143 | struct pcap_ts *pcap_ts; |
| @@ -202,7 +202,7 @@ fail: | |||
| 202 | return err; | 202 | return err; |
| 203 | } | 203 | } |
| 204 | 204 | ||
| 205 | static int pcap_ts_remove(struct platform_device *pdev) | 205 | static int __devexit pcap_ts_remove(struct platform_device *pdev) |
| 206 | { | 206 | { |
| 207 | struct pcap_ts *pcap_ts = platform_get_drvdata(pdev); | 207 | struct pcap_ts *pcap_ts = platform_get_drvdata(pdev); |
| 208 | 208 | ||
| @@ -245,14 +245,26 @@ static const struct dev_pm_ops pcap_ts_pm_ops = { | |||
| 245 | 245 | ||
| 246 | static struct platform_driver pcap_ts_driver = { | 246 | static struct platform_driver pcap_ts_driver = { |
| 247 | .probe = pcap_ts_probe, | 247 | .probe = pcap_ts_probe, |
| 248 | .remove = pcap_ts_remove, | 248 | .remove = __devexit_p(pcap_ts_remove), |
| 249 | .driver = { | 249 | .driver = { |
| 250 | .name = "pcap-ts", | 250 | .name = "pcap-ts", |
| 251 | .owner = THIS_MODULE, | 251 | .owner = THIS_MODULE, |
| 252 | .pm = PCAP_TS_PM_OPS, | 252 | .pm = PCAP_TS_PM_OPS, |
| 253 | }, | 253 | }, |
| 254 | }; | 254 | }; |
| 255 | module_platform_driver(pcap_ts_driver); | 255 | |
| 256 | static int __init pcap_ts_init(void) | ||
| 257 | { | ||
| 258 | return platform_driver_register(&pcap_ts_driver); | ||
| 259 | } | ||
| 260 | |||
| 261 | static void __exit pcap_ts_exit(void) | ||
| 262 | { | ||
| 263 | platform_driver_unregister(&pcap_ts_driver); | ||
| 264 | } | ||
| 265 | |||
| 266 | module_init(pcap_ts_init); | ||
| 267 | module_exit(pcap_ts_exit); | ||
| 256 | 268 | ||
| 257 | MODULE_DESCRIPTION("Motorola PCAP2 touchscreen driver"); | 269 | MODULE_DESCRIPTION("Motorola PCAP2 touchscreen driver"); |
| 258 | MODULE_AUTHOR("Daniel Ribeiro / Harald Welte"); | 270 | MODULE_AUTHOR("Daniel Ribeiro / Harald Welte"); |
diff --git a/drivers/input/touchscreen/penmount.c b/drivers/input/touchscreen/penmount.c index b49f0b83692..c7f9cebebbb 100644 --- a/drivers/input/touchscreen/penmount.c +++ b/drivers/input/touchscreen/penmount.c | |||
| @@ -2,7 +2,6 @@ | |||
| 2 | * Penmount serial touchscreen driver | 2 | * Penmount serial touchscreen driver |
| 3 | * | 3 | * |
| 4 | * Copyright (c) 2006 Rick Koch <n1gp@hotmail.com> | 4 | * Copyright (c) 2006 Rick Koch <n1gp@hotmail.com> |
| 5 | * Copyright (c) 2011 John Sung <penmount.touch@gmail.com> | ||
| 6 | * | 5 | * |
| 7 | * Based on ELO driver (drivers/input/touchscreen/elo.c) | 6 | * Based on ELO driver (drivers/input/touchscreen/elo.c) |
| 8 | * Copyright (c) 2004 Vojtech Pavlik | 7 | * Copyright (c) 2004 Vojtech Pavlik |
| @@ -19,14 +18,12 @@ | |||
| 19 | #include <linux/module.h> | 18 | #include <linux/module.h> |
| 20 | #include <linux/slab.h> | 19 | #include <linux/slab.h> |
| 21 | #include <linux/input.h> | 20 | #include <linux/input.h> |
| 22 | #include <linux/input/mt.h> | ||
| 23 | #include <linux/serio.h> | 21 | #include <linux/serio.h> |
| 24 | #include <linux/init.h> | 22 | #include <linux/init.h> |
| 25 | 23 | ||
| 26 | #define DRIVER_DESC "PenMount serial touchscreen driver" | 24 | #define DRIVER_DESC "Penmount serial touchscreen driver" |
| 27 | 25 | ||
| 28 | MODULE_AUTHOR("Rick Koch <n1gp@hotmail.com>"); | 26 | MODULE_AUTHOR("Rick Koch <n1gp@hotmail.com>"); |
| 29 | MODULE_AUTHOR("John Sung <penmount.touch@gmail.com>"); | ||
| 30 | MODULE_DESCRIPTION(DRIVER_DESC); | 27 | MODULE_DESCRIPTION(DRIVER_DESC); |
| 31 | MODULE_LICENSE("GPL"); | 28 | MODULE_LICENSE("GPL"); |
| 32 | 29 | ||
| @@ -34,19 +31,7 @@ MODULE_LICENSE("GPL"); | |||
| 34 | * Definitions & global arrays. | 31 | * Definitions & global arrays. |
| 35 | */ | 32 | */ |
| 36 | 33 | ||
| 37 | #define PM_MAX_LENGTH 6 | 34 | #define PM_MAX_LENGTH 5 |
| 38 | #define PM_MAX_MTSLOT 16 | ||
| 39 | #define PM_3000_MTSLOT 2 | ||
| 40 | #define PM_6250_MTSLOT 12 | ||
| 41 | |||
| 42 | /* | ||
| 43 | * Multi-touch slot | ||
| 44 | */ | ||
| 45 | |||
| 46 | struct mt_slot { | ||
| 47 | unsigned short x, y; | ||
| 48 | bool active; /* is the touch valid? */ | ||
| 49 | }; | ||
| 50 | 35 | ||
| 51 | /* | 36 | /* |
| 52 | * Per-touchscreen data. | 37 | * Per-touchscreen data. |
| @@ -58,119 +43,25 @@ struct pm { | |||
| 58 | int idx; | 43 | int idx; |
| 59 | unsigned char data[PM_MAX_LENGTH]; | 44 | unsigned char data[PM_MAX_LENGTH]; |
| 60 | char phys[32]; | 45 | char phys[32]; |
| 61 | unsigned char packetsize; | ||
| 62 | unsigned char maxcontacts; | ||
| 63 | struct mt_slot slots[PM_MAX_MTSLOT]; | ||
| 64 | void (*parse_packet)(struct pm *); | ||
| 65 | }; | 46 | }; |
| 66 | 47 | ||
| 67 | /* | ||
| 68 | * pm_mtevent() sends mt events and also emulates pointer movement | ||
| 69 | */ | ||
| 70 | |||
| 71 | static void pm_mtevent(struct pm *pm, struct input_dev *input) | ||
| 72 | { | ||
| 73 | int i; | ||
| 74 | |||
| 75 | for (i = 0; i < pm->maxcontacts; ++i) { | ||
| 76 | input_mt_slot(input, i); | ||
| 77 | input_mt_report_slot_state(input, MT_TOOL_FINGER, | ||
| 78 | pm->slots[i].active); | ||
| 79 | if (pm->slots[i].active) { | ||
| 80 | input_event(input, EV_ABS, ABS_MT_POSITION_X, pm->slots[i].x); | ||
| 81 | input_event(input, EV_ABS, ABS_MT_POSITION_Y, pm->slots[i].y); | ||
| 82 | } | ||
| 83 | } | ||
| 84 | |||
| 85 | input_mt_report_pointer_emulation(input, true); | ||
| 86 | input_sync(input); | ||
| 87 | } | ||
| 88 | |||
| 89 | /* | ||
| 90 | * pm_checkpacket() checks if data packet is valid | ||
| 91 | */ | ||
| 92 | |||
| 93 | static bool pm_checkpacket(unsigned char *packet) | ||
| 94 | { | ||
| 95 | int total = 0; | ||
| 96 | int i; | ||
| 97 | |||
| 98 | for (i = 0; i < 5; i++) | ||
| 99 | total += packet[i]; | ||
| 100 | |||
| 101 | return packet[5] == (unsigned char)~(total & 0xff); | ||
| 102 | } | ||
| 103 | |||
| 104 | static void pm_parse_9000(struct pm *pm) | ||
| 105 | { | ||
| 106 | struct input_dev *dev = pm->dev; | ||
| 107 | |||
| 108 | if ((pm->data[0] & 0x80) && pm->packetsize == ++pm->idx) { | ||
| 109 | input_report_abs(dev, ABS_X, pm->data[1] * 128 + pm->data[2]); | ||
| 110 | input_report_abs(dev, ABS_Y, pm->data[3] * 128 + pm->data[4]); | ||
| 111 | input_report_key(dev, BTN_TOUCH, !!(pm->data[0] & 0x40)); | ||
| 112 | input_sync(dev); | ||
| 113 | pm->idx = 0; | ||
| 114 | } | ||
| 115 | } | ||
| 116 | |||
| 117 | static void pm_parse_6000(struct pm *pm) | ||
| 118 | { | ||
| 119 | struct input_dev *dev = pm->dev; | ||
| 120 | |||
| 121 | if ((pm->data[0] & 0xbf) == 0x30 && pm->packetsize == ++pm->idx) { | ||
| 122 | if (pm_checkpacket(pm->data)) { | ||
| 123 | input_report_abs(dev, ABS_X, | ||
| 124 | pm->data[2] * 256 + pm->data[1]); | ||
| 125 | input_report_abs(dev, ABS_Y, | ||
| 126 | pm->data[4] * 256 + pm->data[3]); | ||
| 127 | input_report_key(dev, BTN_TOUCH, pm->data[0] & 0x40); | ||
| 128 | input_sync(dev); | ||
| 129 | } | ||
| 130 | pm->idx = 0; | ||
| 131 | } | ||
| 132 | } | ||
| 133 | |||
| 134 | static void pm_parse_3000(struct pm *pm) | ||
| 135 | { | ||
| 136 | struct input_dev *dev = pm->dev; | ||
| 137 | |||
| 138 | if ((pm->data[0] & 0xce) == 0x40 && pm->packetsize == ++pm->idx) { | ||
| 139 | if (pm_checkpacket(pm->data)) { | ||
| 140 | int slotnum = pm->data[0] & 0x0f; | ||
| 141 | pm->slots[slotnum].active = pm->data[0] & 0x30; | ||
| 142 | pm->slots[slotnum].x = pm->data[2] * 256 + pm->data[1]; | ||
| 143 | pm->slots[slotnum].y = pm->data[4] * 256 + pm->data[3]; | ||
| 144 | pm_mtevent(pm, dev); | ||
| 145 | } | ||
| 146 | pm->idx = 0; | ||
| 147 | } | ||
| 148 | } | ||
| 149 | |||
| 150 | static void pm_parse_6250(struct pm *pm) | ||
| 151 | { | ||
| 152 | struct input_dev *dev = pm->dev; | ||
| 153 | |||
| 154 | if ((pm->data[0] & 0xb0) == 0x30 && pm->packetsize == ++pm->idx) { | ||
| 155 | if (pm_checkpacket(pm->data)) { | ||
| 156 | int slotnum = pm->data[0] & 0x0f; | ||
| 157 | pm->slots[slotnum].active = pm->data[0] & 0x40; | ||
| 158 | pm->slots[slotnum].x = pm->data[2] * 256 + pm->data[1]; | ||
| 159 | pm->slots[slotnum].y = pm->data[4] * 256 + pm->data[3]; | ||
| 160 | pm_mtevent(pm, dev); | ||
| 161 | } | ||
| 162 | pm->idx = 0; | ||
| 163 | } | ||
| 164 | } | ||
| 165 | |||
| 166 | static irqreturn_t pm_interrupt(struct serio *serio, | 48 | static irqreturn_t pm_interrupt(struct serio *serio, |
| 167 | unsigned char data, unsigned int flags) | 49 | unsigned char data, unsigned int flags) |
| 168 | { | 50 | { |
| 169 | struct pm *pm = serio_get_drvdata(serio); | 51 | struct pm *pm = serio_get_drvdata(serio); |
| 52 | struct input_dev *dev = pm->dev; | ||
| 170 | 53 | ||
| 171 | pm->data[pm->idx] = data; | 54 | pm->data[pm->idx] = data; |
| 172 | 55 | ||
| 173 | pm->parse_packet(pm); | 56 | if (pm->data[0] & 0x80) { |
| 57 | if (PM_MAX_LENGTH == ++pm->idx) { | ||
| 58 | input_report_abs(dev, ABS_X, pm->data[2] * 128 + pm->data[1]); | ||
| 59 | input_report_abs(dev, ABS_Y, pm->data[4] * 128 + pm->data[3]); | ||
| 60 | input_report_key(dev, BTN_TOUCH, !!(pm->data[0] & 0x40)); | ||
| 61 | input_sync(dev); | ||
| 62 | pm->idx = 0; | ||
| 63 | } | ||
| 64 | } | ||
| 174 | 65 | ||
| 175 | return IRQ_HANDLED; | 66 | return IRQ_HANDLED; |
| 176 | } | 67 | } |
| @@ -183,17 +74,17 @@ static void pm_disconnect(struct serio *serio) | |||
| 183 | { | 74 | { |
| 184 | struct pm *pm = serio_get_drvdata(serio); | 75 | struct pm *pm = serio_get_drvdata(serio); |
| 185 | 76 | ||
| 186 | serio_close(serio); | 77 | input_get_device(pm->dev); |
| 187 | |||
| 188 | input_unregister_device(pm->dev); | 78 | input_unregister_device(pm->dev); |
| 189 | kfree(pm); | 79 | serio_close(serio); |
| 190 | |||
| 191 | serio_set_drvdata(serio, NULL); | 80 | serio_set_drvdata(serio, NULL); |
| 81 | input_put_device(pm->dev); | ||
| 82 | kfree(pm); | ||
| 192 | } | 83 | } |
| 193 | 84 | ||
| 194 | /* | 85 | /* |
| 195 | * pm_connect() is the routine that is called when someone adds a | 86 | * pm_connect() is the routine that is called when someone adds a |
| 196 | * new serio device that supports PenMount protocol and registers it as | 87 | * new serio device that supports Gunze protocol and registers it as |
| 197 | * an input device. | 88 | * an input device. |
| 198 | */ | 89 | */ |
| 199 | 90 | ||
| @@ -201,7 +92,6 @@ static int pm_connect(struct serio *serio, struct serio_driver *drv) | |||
| 201 | { | 92 | { |
| 202 | struct pm *pm; | 93 | struct pm *pm; |
| 203 | struct input_dev *input_dev; | 94 | struct input_dev *input_dev; |
| 204 | int max_x, max_y; | ||
| 205 | int err; | 95 | int err; |
| 206 | 96 | ||
| 207 | pm = kzalloc(sizeof(struct pm), GFP_KERNEL); | 97 | pm = kzalloc(sizeof(struct pm), GFP_KERNEL); |
| @@ -214,9 +104,8 @@ static int pm_connect(struct serio *serio, struct serio_driver *drv) | |||
| 214 | pm->serio = serio; | 104 | pm->serio = serio; |
| 215 | pm->dev = input_dev; | 105 | pm->dev = input_dev; |
| 216 | snprintf(pm->phys, sizeof(pm->phys), "%s/input0", serio->phys); | 106 | snprintf(pm->phys, sizeof(pm->phys), "%s/input0", serio->phys); |
| 217 | pm->maxcontacts = 1; | ||
| 218 | 107 | ||
| 219 | input_dev->name = "PenMount Serial TouchScreen"; | 108 | input_dev->name = "Penmount Serial TouchScreen"; |
| 220 | input_dev->phys = pm->phys; | 109 | input_dev->phys = pm->phys; |
| 221 | input_dev->id.bustype = BUS_RS232; | 110 | input_dev->id.bustype = BUS_RS232; |
| 222 | input_dev->id.vendor = SERIO_PENMOUNT; | 111 | input_dev->id.vendor = SERIO_PENMOUNT; |
| @@ -224,52 +113,10 @@ static int pm_connect(struct serio *serio, struct serio_driver *drv) | |||
| 224 | input_dev->id.version = 0x0100; | 113 | input_dev->id.version = 0x0100; |
| 225 | input_dev->dev.parent = &serio->dev; | 114 | input_dev->dev.parent = &serio->dev; |
| 226 | 115 | ||
| 227 | input_dev->evbit[0] = BIT_MASK(EV_KEY) | BIT_MASK(EV_ABS); | 116 | input_dev->evbit[0] = BIT_MASK(EV_KEY) | BIT_MASK(EV_ABS); |
| 228 | input_dev->keybit[BIT_WORD(BTN_TOUCH)] = BIT_MASK(BTN_TOUCH); | 117 | input_dev->keybit[BIT_WORD(BTN_TOUCH)] = BIT_MASK(BTN_TOUCH); |
| 229 | 118 | input_set_abs_params(pm->dev, ABS_X, 0, 0x3ff, 0, 0); | |
| 230 | switch (serio->id.id) { | 119 | input_set_abs_params(pm->dev, ABS_Y, 0, 0x3ff, 0, 0); |
| 231 | default: | ||
| 232 | case 0: | ||
| 233 | pm->packetsize = 5; | ||
| 234 | pm->parse_packet = pm_parse_9000; | ||
| 235 | input_dev->id.product = 0x9000; | ||
| 236 | max_x = max_y = 0x3ff; | ||
| 237 | break; | ||
| 238 | |||
| 239 | case 1: | ||
| 240 | pm->packetsize = 6; | ||
| 241 | pm->parse_packet = pm_parse_6000; | ||
| 242 | input_dev->id.product = 0x6000; | ||
| 243 | max_x = max_y = 0x3ff; | ||
| 244 | break; | ||
| 245 | |||
| 246 | case 2: | ||
| 247 | pm->packetsize = 6; | ||
| 248 | pm->parse_packet = pm_parse_3000; | ||
| 249 | input_dev->id.product = 0x3000; | ||
| 250 | max_x = max_y = 0x7ff; | ||
| 251 | pm->maxcontacts = PM_3000_MTSLOT; | ||
| 252 | break; | ||
| 253 | |||
| 254 | case 3: | ||
| 255 | pm->packetsize = 6; | ||
| 256 | pm->parse_packet = pm_parse_6250; | ||
| 257 | input_dev->id.product = 0x6250; | ||
| 258 | max_x = max_y = 0x3ff; | ||
| 259 | pm->maxcontacts = PM_6250_MTSLOT; | ||
| 260 | break; | ||
| 261 | } | ||
| 262 | |||
| 263 | input_set_abs_params(pm->dev, ABS_X, 0, max_x, 0, 0); | ||
| 264 | input_set_abs_params(pm->dev, ABS_Y, 0, max_y, 0, 0); | ||
| 265 | |||
| 266 | if (pm->maxcontacts > 1) { | ||
| 267 | input_mt_init_slots(pm->dev, pm->maxcontacts, 0); | ||
| 268 | input_set_abs_params(pm->dev, | ||
| 269 | ABS_MT_POSITION_X, 0, max_x, 0, 0); | ||
| 270 | input_set_abs_params(pm->dev, | ||
| 271 | ABS_MT_POSITION_Y, 0, max_y, 0, 0); | ||
| 272 | } | ||
| 273 | 120 | ||
| 274 | serio_set_drvdata(serio, pm); | 121 | serio_set_drvdata(serio, pm); |
| 275 | 122 | ||
| @@ -308,7 +155,7 @@ MODULE_DEVICE_TABLE(serio, pm_serio_ids); | |||
| 308 | 155 | ||
| 309 | static struct serio_driver pm_drv = { | 156 | static struct serio_driver pm_drv = { |
| 310 | .driver = { | 157 | .driver = { |
| 311 | .name = "serio-penmount", | 158 | .name = "penmountlpc", |
| 312 | }, | 159 | }, |
| 313 | .description = DRIVER_DESC, | 160 | .description = DRIVER_DESC, |
| 314 | .id_table = pm_serio_ids, | 161 | .id_table = pm_serio_ids, |
| @@ -317,4 +164,19 @@ static struct serio_driver pm_drv = { | |||
| 317 | .disconnect = pm_disconnect, | 164 | .disconnect = pm_disconnect, |
| 318 | }; | 165 | }; |
| 319 | 166 | ||
| 320 | module_serio_driver(pm_drv); | 167 | /* |
| 168 | * The functions for inserting/removing us as a module. | ||
| 169 | */ | ||
| 170 | |||
| 171 | static int __init pm_init(void) | ||
| 172 | { | ||
| 173 | return serio_register_driver(&pm_drv); | ||
| 174 | } | ||
| 175 | |||
| 176 | static void __exit pm_exit(void) | ||
| 177 | { | ||
| 178 | serio_unregister_driver(&pm_drv); | ||
| 179 | } | ||
| 180 | |||
| 181 | module_init(pm_init); | ||
| 182 | module_exit(pm_exit); | ||
diff --git a/drivers/input/touchscreen/pixcir_i2c_ts.c b/drivers/input/touchscreen/pixcir_i2c_ts.c deleted file mode 100644 index 6cc6b36663f..00000000000 --- a/drivers/input/touchscreen/pixcir_i2c_ts.c +++ /dev/null | |||
| @@ -1,229 +0,0 @@ | |||
| 1 | /* | ||
| 2 | * Driver for Pixcir I2C touchscreen controllers. | ||
| 3 | * | ||
| 4 | * Copyright (C) 2010-2011 Pixcir, Inc. | ||
| 5 | * | ||
| 6 | * This software is licensed under the terms of the GNU General Public | ||
| 7 | * License version 2, as published by the Free Software Foundation, and | ||
| 8 | * may be copied, distributed, and modified under those terms. | ||
| 9 | * | ||
| 10 | * This program is distributed in the hope that it will be useful, | ||
| 11 | * but WITHOUT ANY WARRANTY; without even the implied warranty of | ||
| 12 | * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the | ||
| 13 | * GNU General Public License for more details. | ||
| 14 | * | ||
| 15 | * You should have received a copy of the GNU General Public | ||
| 16 | * License along with this library; if not, write to the Free Software | ||
| 17 | * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA | ||
| 18 | */ | ||
| 19 | |||
| 20 | #include <linux/delay.h> | ||
| 21 | #include <linux/module.h> | ||
| 22 | #include <linux/interrupt.h> | ||
| 23 | #include <linux/slab.h> | ||
| 24 | #include <linux/i2c.h> | ||
| 25 | #include <linux/input.h> | ||
| 26 | #include <linux/input/pixcir_ts.h> | ||
| 27 | |||
| 28 | struct pixcir_i2c_ts_data { | ||
| 29 | struct i2c_client *client; | ||
| 30 | struct input_dev *input; | ||
| 31 | const struct pixcir_ts_platform_data *chip; | ||
| 32 | bool exiting; | ||
| 33 | }; | ||
| 34 | |||
| 35 | static void pixcir_ts_poscheck(struct pixcir_i2c_ts_data *data) | ||
| 36 | { | ||
| 37 | struct pixcir_i2c_ts_data *tsdata = data; | ||
| 38 | u8 rdbuf[10], wrbuf[1] = { 0 }; | ||
| 39 | u8 touch; | ||
| 40 | int ret; | ||
| 41 | |||
| 42 | ret = i2c_master_send(tsdata->client, wrbuf, sizeof(wrbuf)); | ||
| 43 | if (ret != sizeof(wrbuf)) { | ||
| 44 | dev_err(&tsdata->client->dev, | ||
| 45 | "%s: i2c_master_send failed(), ret=%d\n", | ||
| 46 | __func__, ret); | ||
| 47 | return; | ||
| 48 | } | ||
| 49 | |||
| 50 | ret = i2c_master_recv(tsdata->client, rdbuf, sizeof(rdbuf)); | ||
| 51 | if (ret != sizeof(rdbuf)) { | ||
| 52 | dev_err(&tsdata->client->dev, | ||
| 53 | "%s: i2c_master_recv failed(), ret=%d\n", | ||
| 54 | __func__, ret); | ||
| 55 | return; | ||
| 56 | } | ||
| 57 | |||
| 58 | touch = rdbuf[0]; | ||
| 59 | if (touch) { | ||
| 60 | u16 posx1 = (rdbuf[3] << 8) | rdbuf[2]; | ||
| 61 | u16 posy1 = (rdbuf[5] << 8) | rdbuf[4]; | ||
| 62 | u16 posx2 = (rdbuf[7] << 8) | rdbuf[6]; | ||
| 63 | u16 posy2 = (rdbuf[9] << 8) | rdbuf[8]; | ||
| 64 | |||
| 65 | input_report_key(tsdata->input, BTN_TOUCH, 1); | ||
| 66 | input_report_abs(tsdata->input, ABS_X, posx1); | ||
| 67 | input_report_abs(tsdata->input, ABS_Y, posy1); | ||
| 68 | |||
| 69 | input_report_abs(tsdata->input, ABS_MT_POSITION_X, posx1); | ||
| 70 | input_report_abs(tsdata->input, ABS_MT_POSITION_Y, posy1); | ||
| 71 | input_mt_sync(tsdata->input); | ||
| 72 | |||
| 73 | if (touch == 2) { | ||
| 74 | input_report_abs(tsdata->input, | ||
| 75 | ABS_MT_POSITION_X, posx2); | ||
| 76 | input_report_abs(tsdata->input, | ||
| 77 | ABS_MT_POSITION_Y, posy2); | ||
| 78 | input_mt_sync(tsdata->input); | ||
| 79 | } | ||
| 80 | } else { | ||
| 81 | input_report_key(tsdata->input, BTN_TOUCH, 0); | ||
| 82 | } | ||
| 83 | |||
| 84 | input_sync(tsdata->input); | ||
| 85 | } | ||
| 86 | |||
| 87 | static irqreturn_t pixcir_ts_isr(int irq, void *dev_id) | ||
| 88 | { | ||
| 89 | struct pixcir_i2c_ts_data *tsdata = dev_id; | ||
| 90 | |||
| 91 | while (!tsdata->exiting) { | ||
| 92 | pixcir_ts_poscheck(tsdata); | ||
| 93 | |||
| 94 | if (tsdata->chip->attb_read_val()) | ||
| 95 | break; | ||
| 96 | |||
| 97 | msleep(20); | ||
| 98 | } | ||
| 99 | |||
| 100 | return IRQ_HANDLED; | ||
| 101 | } | ||
| 102 | |||
| 103 | #ifdef CONFIG_PM_SLEEP | ||
| 104 | static int pixcir_i2c_ts_suspend(struct device *dev) | ||
| 105 | { | ||
| 106 | struct i2c_client *client = to_i2c_client(dev); | ||
| 107 | |||
| 108 | if (device_may_wakeup(&client->dev)) | ||
| 109 | enable_irq_wake(client->irq); | ||
| 110 | |||
| 111 | return 0; | ||
| 112 | } | ||
| 113 | |||
| 114 | static int pixcir_i2c_ts_resume(struct device *dev) | ||
| 115 | { | ||
| 116 | struct i2c_client *client = to_i2c_client(dev); | ||
| 117 | |||
| 118 | if (device_may_wakeup(&client->dev)) | ||
| 119 | disable_irq_wake(client->irq); | ||
| 120 | |||
| 121 | return 0; | ||
| 122 | } | ||
| 123 | #endif | ||
| 124 | |||
| 125 | static SIMPLE_DEV_PM_OPS(pixcir_dev_pm_ops, | ||
| 126 | pixcir_i2c_ts_suspend, pixcir_i2c_ts_resume); | ||
| 127 | |||
| 128 | static int pixcir_i2c_ts_probe(struct i2c_client *client, | ||
| 129 | const struct i2c_device_id *id) | ||
| 130 | { | ||
| 131 | const struct pixcir_ts_platform_data *pdata = client->dev.platform_data; | ||
| 132 | struct pixcir_i2c_ts_data *tsdata; | ||
| 133 | struct input_dev *input; | ||
| 134 | int error; | ||
| 135 | |||
| 136 | if (!pdata) { | ||
| 137 | dev_err(&client->dev, "platform data not defined\n"); | ||
| 138 | return -EINVAL; | ||
| 139 | } | ||
| 140 | |||
| 141 | tsdata = kzalloc(sizeof(*tsdata), GFP_KERNEL); | ||
| 142 | input = input_allocate_device(); | ||
| 143 | if (!tsdata || !input) { | ||
| 144 | dev_err(&client->dev, "Failed to allocate driver data!\n"); | ||
| 145 | error = -ENOMEM; | ||
| 146 | goto err_free_mem; | ||
| 147 | } | ||
| 148 | |||
| 149 | tsdata->client = client; | ||
| 150 | tsdata->input = input; | ||
| 151 | tsdata->chip = pdata; | ||
| 152 | |||
| 153 | input->name = client->name; | ||
| 154 | input->id.bustype = BUS_I2C; | ||
| 155 | input->dev.parent = &client->dev; | ||
| 156 | |||
| 157 | __set_bit(EV_KEY, input->evbit); | ||
| 158 | __set_bit(EV_ABS, input->evbit); | ||
| 159 | __set_bit(BTN_TOUCH, input->keybit); | ||
| 160 | input_set_abs_params(input, ABS_X, 0, pdata->x_max, 0, 0); | ||
| 161 | input_set_abs_params(input, ABS_Y, 0, pdata->y_max, 0, 0); | ||
| 162 | input_set_abs_params(input, ABS_MT_POSITION_X, 0, pdata->x_max, 0, 0); | ||
| 163 | input_set_abs_params(input, ABS_MT_POSITION_Y, 0, pdata->y_max, 0, 0); | ||
| 164 | |||
| 165 | input_set_drvdata(input, tsdata); | ||
| 166 | |||
| 167 | error = request_threaded_irq(client->irq, NULL, pixcir_ts_isr, | ||
| 168 | IRQF_TRIGGER_FALLING | IRQF_ONESHOT, | ||
| 169 | client->name, tsdata); | ||
| 170 | if (error) { | ||
| 171 | dev_err(&client->dev, "Unable to request touchscreen IRQ.\n"); | ||
| 172 | goto err_free_mem; | ||
| 173 | } | ||
| 174 | |||
| 175 | error = input_register_device(input); | ||
| 176 | if (error) | ||
| 177 | goto err_free_irq; | ||
| 178 | |||
| 179 | i2c_set_clientdata(client, tsdata); | ||
| 180 | device_init_wakeup(&client->dev, 1); | ||
| 181 | |||
| 182 | return 0; | ||
| 183 | |||
| 184 | err_free_irq: | ||
| 185 | free_irq(client->irq, tsdata); | ||
| 186 | err_free_mem: | ||
| 187 | input_free_device(input); | ||
| 188 | kfree(tsdata); | ||
| 189 | return error; | ||
| 190 | } | ||
| 191 | |||
| 192 | static int pixcir_i2c_ts_remove(struct i2c_client *client) | ||
| 193 | { | ||
| 194 | struct pixcir_i2c_ts_data *tsdata = i2c_get_clientdata(client); | ||
| 195 | |||
| 196 | device_init_wakeup(&client->dev, 0); | ||
| 197 | |||
| 198 | tsdata->exiting = true; | ||
| 199 | mb(); | ||
| 200 | free_irq(client->irq, tsdata); | ||
| 201 | |||
| 202 | input_unregister_device(tsdata->input); | ||
| 203 | kfree(tsdata); | ||
| 204 | |||
| 205 | return 0; | ||
| 206 | } | ||
| 207 | |||
| 208 | static const struct i2c_device_id pixcir_i2c_ts_id[] = { | ||
| 209 | { "pixcir_ts", 0 }, | ||
| 210 | { } | ||
| 211 | }; | ||
| 212 | MODULE_DEVICE_TABLE(i2c, pixcir_i2c_ts_id); | ||
| 213 | |||
| 214 | static struct i2c_driver pixcir_i2c_ts_driver = { | ||
| 215 | .driver = { | ||
| 216 | .owner = THIS_MODULE, | ||
| 217 | .name = "pixcir_ts", | ||
| 218 | .pm = &pixcir_dev_pm_ops, | ||
| 219 | }, | ||
| 220 | .probe = pixcir_i2c_ts_probe, | ||
| 221 | .remove = pixcir_i2c_ts_remove, | ||
| 222 | .id_table = pixcir_i2c_ts_id, | ||
| 223 | }; | ||
| 224 | |||
| 225 | module_i2c_driver(pixcir_i2c_ts_driver); | ||
| 226 | |||
| 227 | MODULE_AUTHOR("Jianchun Bian <jcbian@pixcir.com.cn>, Dequan Meng <dqmeng@pixcir.com.cn>"); | ||
| 228 | MODULE_DESCRIPTION("Pixcir I2C Touchscreen Driver"); | ||
| 229 | MODULE_LICENSE("GPL"); | ||
diff --git a/drivers/input/touchscreen/s3c2410_ts.c b/drivers/input/touchscreen/s3c2410_ts.c index b061af2c837..8feb7f3c8be 100644 --- a/drivers/input/touchscreen/s3c2410_ts.c +++ b/drivers/input/touchscreen/s3c2410_ts.c | |||
| @@ -37,7 +37,7 @@ | |||
| 37 | 37 | ||
| 38 | #include <plat/adc.h> | 38 | #include <plat/adc.h> |
| 39 | #include <plat/regs-adc.h> | 39 | #include <plat/regs-adc.h> |
| 40 | #include <linux/platform_data/touchscreen-s3c2410.h> | 40 | #include <plat/ts.h> |
| 41 | 41 | ||
| 42 | #define TSC_SLEEP (S3C2410_ADCTSC_PULL_UP_DISABLE | S3C2410_ADCTSC_XY_PST(0)) | 42 | #define TSC_SLEEP (S3C2410_ADCTSC_PULL_UP_DISABLE | S3C2410_ADCTSC_XY_PST(0)) |
| 43 | 43 | ||
| @@ -238,7 +238,7 @@ static void s3c24xx_ts_select(struct s3c_adc_client *client, unsigned select) | |||
| 238 | * Initialise, find and allocate any resources we need to run and then | 238 | * Initialise, find and allocate any resources we need to run and then |
| 239 | * register with the ADC and input systems. | 239 | * register with the ADC and input systems. |
| 240 | */ | 240 | */ |
| 241 | static int s3c2410ts_probe(struct platform_device *pdev) | 241 | static int __devinit s3c2410ts_probe(struct platform_device *pdev) |
| 242 | { | 242 | { |
| 243 | struct s3c2410_ts_mach_info *info; | 243 | struct s3c2410_ts_mach_info *info; |
| 244 | struct device *dev = &pdev->dev; | 244 | struct device *dev = &pdev->dev; |
| @@ -328,7 +328,7 @@ static int s3c2410ts_probe(struct platform_device *pdev) | |||
| 328 | ts.shift = info->oversampling_shift; | 328 | ts.shift = info->oversampling_shift; |
| 329 | ts.features = platform_get_device_id(pdev)->driver_data; | 329 | ts.features = platform_get_device_id(pdev)->driver_data; |
| 330 | 330 | ||
| 331 | ret = request_irq(ts.irq_tc, stylus_irq, 0, | 331 | ret = request_irq(ts.irq_tc, stylus_irq, IRQF_DISABLED, |
| 332 | "s3c2410_ts_pen", ts.input); | 332 | "s3c2410_ts_pen", ts.input); |
| 333 | if (ret) { | 333 | if (ret) { |
| 334 | dev_err(dev, "cannot get TC interrupt\n"); | 334 | dev_err(dev, "cannot get TC interrupt\n"); |
| @@ -365,7 +365,7 @@ static int s3c2410ts_probe(struct platform_device *pdev) | |||
| 365 | * | 365 | * |
| 366 | * Free up our state ready to be removed. | 366 | * Free up our state ready to be removed. |
| 367 | */ | 367 | */ |
| 368 | static int s3c2410ts_remove(struct platform_device *pdev) | 368 | static int __devexit s3c2410ts_remove(struct platform_device *pdev) |
| 369 | { | 369 | { |
| 370 | free_irq(ts.irq_tc, ts.input); | 370 | free_irq(ts.irq_tc, ts.input); |
| 371 | del_timer_sync(&touch_timer); | 371 | del_timer_sync(&touch_timer); |
| @@ -406,7 +406,7 @@ static int s3c2410ts_resume(struct device *dev) | |||
| 406 | return 0; | 406 | return 0; |
| 407 | } | 407 | } |
| 408 | 408 | ||
| 409 | static const struct dev_pm_ops s3c_ts_pmops = { | 409 | static struct dev_pm_ops s3c_ts_pmops = { |
| 410 | .suspend = s3c2410ts_suspend, | 410 | .suspend = s3c2410ts_suspend, |
| 411 | .resume = s3c2410ts_resume, | 411 | .resume = s3c2410ts_resume, |
| 412 | }; | 412 | }; |
| @@ -430,9 +430,21 @@ static struct platform_driver s3c_ts_driver = { | |||
| 430 | }, | 430 | }, |
| 431 | .id_table = s3cts_driver_ids, | 431 | .id_table = s3cts_driver_ids, |
| 432 | .probe = s3c2410ts_probe, | 432 | .probe = s3c2410ts_probe, |
| 433 | .remove = s3c2410ts_remove, | 433 | .remove = __devexit_p(s3c2410ts_remove), |
| 434 | }; | 434 | }; |
| 435 | module_platform_driver(s3c_ts_driver); | 435 | |
| 436 | static int __init s3c2410ts_init(void) | ||
| 437 | { | ||
| 438 | return platform_driver_register(&s3c_ts_driver); | ||
| 439 | } | ||
| 440 | |||
| 441 | static void __exit s3c2410ts_exit(void) | ||
| 442 | { | ||
| 443 | platform_driver_unregister(&s3c_ts_driver); | ||
| 444 | } | ||
| 445 | |||
| 446 | module_init(s3c2410ts_init); | ||
| 447 | module_exit(s3c2410ts_exit); | ||
| 436 | 448 | ||
| 437 | MODULE_AUTHOR("Arnaud Patard <arnaud.patard@rtp-net.org>, " | 449 | MODULE_AUTHOR("Arnaud Patard <arnaud.patard@rtp-net.org>, " |
| 438 | "Ben Dooks <ben@simtec.co.uk>, " | 450 | "Ben Dooks <ben@simtec.co.uk>, " |
diff --git a/drivers/input/touchscreen/st1232.c b/drivers/input/touchscreen/st1232.c index d9d05e22242..4ab371358b3 100644 --- a/drivers/input/touchscreen/st1232.c +++ b/drivers/input/touchscreen/st1232.c | |||
| @@ -23,7 +23,6 @@ | |||
| 23 | #include <linux/input.h> | 23 | #include <linux/input.h> |
| 24 | #include <linux/interrupt.h> | 24 | #include <linux/interrupt.h> |
| 25 | #include <linux/module.h> | 25 | #include <linux/module.h> |
| 26 | #include <linux/pm_qos.h> | ||
| 27 | #include <linux/slab.h> | 26 | #include <linux/slab.h> |
| 28 | #include <linux/types.h> | 27 | #include <linux/types.h> |
| 29 | 28 | ||
| @@ -47,7 +46,6 @@ struct st1232_ts_data { | |||
| 47 | struct i2c_client *client; | 46 | struct i2c_client *client; |
| 48 | struct input_dev *input_dev; | 47 | struct input_dev *input_dev; |
| 49 | struct st1232_ts_finger finger[MAX_FINGERS]; | 48 | struct st1232_ts_finger finger[MAX_FINGERS]; |
| 50 | struct dev_pm_qos_request low_latency_req; | ||
| 51 | }; | 49 | }; |
| 52 | 50 | ||
| 53 | static int st1232_ts_read_data(struct st1232_ts_data *ts) | 51 | static int st1232_ts_read_data(struct st1232_ts_data *ts) |
| @@ -120,17 +118,8 @@ static irqreturn_t st1232_ts_irq_handler(int irq, void *dev_id) | |||
| 120 | } | 118 | } |
| 121 | 119 | ||
| 122 | /* SYN_MT_REPORT only if no contact */ | 120 | /* SYN_MT_REPORT only if no contact */ |
| 123 | if (!count) { | 121 | if (!count) |
| 124 | input_mt_sync(input_dev); | 122 | input_mt_sync(input_dev); |
| 125 | if (ts->low_latency_req.dev) { | ||
| 126 | dev_pm_qos_remove_request(&ts->low_latency_req); | ||
| 127 | ts->low_latency_req.dev = NULL; | ||
| 128 | } | ||
| 129 | } else if (!ts->low_latency_req.dev) { | ||
| 130 | /* First contact, request 100 us latency. */ | ||
| 131 | dev_pm_qos_add_ancestor_request(&ts->client->dev, | ||
| 132 | &ts->low_latency_req, 100); | ||
| 133 | } | ||
| 134 | 123 | ||
| 135 | /* SYN_REPORT */ | 124 | /* SYN_REPORT */ |
| 136 | input_sync(input_dev); | 125 | input_sync(input_dev); |
| @@ -139,7 +128,7 @@ end: | |||
| 139 | return IRQ_HANDLED; | 128 | return IRQ_HANDLED; |
| 140 | } | 129 | } |
| 141 | 130 | ||
| 142 | static int st1232_ts_probe(struct i2c_client *client, | 131 | static int __devinit st1232_ts_probe(struct i2c_client *client, |
| 143 | const struct i2c_device_id *id) | 132 | const struct i2c_device_id *id) |
| 144 | { | 133 | { |
| 145 | struct st1232_ts_data *ts; | 134 | struct st1232_ts_data *ts; |
| @@ -206,7 +195,7 @@ err_free_mem: | |||
| 206 | return error; | 195 | return error; |
| 207 | } | 196 | } |
| 208 | 197 | ||
| 209 | static int st1232_ts_remove(struct i2c_client *client) | 198 | static int __devexit st1232_ts_remove(struct i2c_client *client) |
| 210 | { | 199 | { |
| 211 | struct st1232_ts_data *ts = i2c_get_clientdata(client); | 200 | struct st1232_ts_data *ts = i2c_get_clientdata(client); |
| 212 | 201 | ||
| @@ -218,7 +207,7 @@ static int st1232_ts_remove(struct i2c_client *client) | |||
| 218 | return 0; | 207 | return 0; |
| 219 | } | 208 | } |
| 220 | 209 | ||
| 221 | #ifdef CONFIG_PM_SLEEP | 210 | #ifdef CONFIG_PM |
| 222 | static int st1232_ts_suspend(struct device *dev) | 211 | static int st1232_ts_suspend(struct device *dev) |
| 223 | { | 212 | { |
| 224 | struct i2c_client *client = to_i2c_client(dev); | 213 | struct i2c_client *client = to_i2c_client(dev); |
| @@ -243,38 +232,42 @@ static int st1232_ts_resume(struct device *dev) | |||
| 243 | return 0; | 232 | return 0; |
| 244 | } | 233 | } |
| 245 | 234 | ||
| 235 | static const struct dev_pm_ops st1232_ts_pm_ops = { | ||
| 236 | .suspend = st1232_ts_suspend, | ||
| 237 | .resume = st1232_ts_resume, | ||
| 238 | }; | ||
| 246 | #endif | 239 | #endif |
| 247 | 240 | ||
| 248 | static SIMPLE_DEV_PM_OPS(st1232_ts_pm_ops, | ||
| 249 | st1232_ts_suspend, st1232_ts_resume); | ||
| 250 | |||
| 251 | static const struct i2c_device_id st1232_ts_id[] = { | 241 | static const struct i2c_device_id st1232_ts_id[] = { |
| 252 | { ST1232_TS_NAME, 0 }, | 242 | { ST1232_TS_NAME, 0 }, |
| 253 | { } | 243 | { } |
| 254 | }; | 244 | }; |
| 255 | MODULE_DEVICE_TABLE(i2c, st1232_ts_id); | 245 | MODULE_DEVICE_TABLE(i2c, st1232_ts_id); |
| 256 | 246 | ||
| 257 | #ifdef CONFIG_OF | ||
| 258 | static const struct of_device_id st1232_ts_dt_ids[] = { | ||
| 259 | { .compatible = "sitronix,st1232", }, | ||
| 260 | { } | ||
| 261 | }; | ||
| 262 | MODULE_DEVICE_TABLE(of, st1232_ts_dt_ids); | ||
| 263 | #endif | ||
| 264 | |||
| 265 | static struct i2c_driver st1232_ts_driver = { | 247 | static struct i2c_driver st1232_ts_driver = { |
| 266 | .probe = st1232_ts_probe, | 248 | .probe = st1232_ts_probe, |
| 267 | .remove = st1232_ts_remove, | 249 | .remove = __devexit_p(st1232_ts_remove), |
| 268 | .id_table = st1232_ts_id, | 250 | .id_table = st1232_ts_id, |
| 269 | .driver = { | 251 | .driver = { |
| 270 | .name = ST1232_TS_NAME, | 252 | .name = ST1232_TS_NAME, |
| 271 | .owner = THIS_MODULE, | 253 | .owner = THIS_MODULE, |
| 272 | .of_match_table = of_match_ptr(st1232_ts_dt_ids), | 254 | #ifdef CONFIG_PM |
| 273 | .pm = &st1232_ts_pm_ops, | 255 | .pm = &st1232_ts_pm_ops, |
| 256 | #endif | ||
| 274 | }, | 257 | }, |
| 275 | }; | 258 | }; |
| 276 | 259 | ||
| 277 | module_i2c_driver(st1232_ts_driver); | 260 | static int __init st1232_ts_init(void) |
| 261 | { | ||
| 262 | return i2c_add_driver(&st1232_ts_driver); | ||
| 263 | } | ||
| 264 | module_init(st1232_ts_init); | ||
| 265 | |||
| 266 | static void __exit st1232_ts_exit(void) | ||
| 267 | { | ||
| 268 | i2c_del_driver(&st1232_ts_driver); | ||
| 269 | } | ||
| 270 | module_exit(st1232_ts_exit); | ||
| 278 | 271 | ||
| 279 | MODULE_AUTHOR("Tony SIM <chinyeow.sim.xt@renesas.com>"); | 272 | MODULE_AUTHOR("Tony SIM <chinyeow.sim.xt@renesas.com>"); |
| 280 | MODULE_DESCRIPTION("SITRONIX ST1232 Touchscreen Controller Driver"); | 273 | MODULE_DESCRIPTION("SITRONIX ST1232 Touchscreen Controller Driver"); |
diff --git a/drivers/input/touchscreen/stmpe-ts.c b/drivers/input/touchscreen/stmpe-ts.c index 84d884b4ec3..ae88e13c99f 100644 --- a/drivers/input/touchscreen/stmpe-ts.c +++ b/drivers/input/touchscreen/stmpe-ts.c | |||
| @@ -1,5 +1,4 @@ | |||
| 1 | /* | 1 | /* STMicroelectronics STMPE811 Touchscreen Driver |
| 2 | * STMicroelectronics STMPE811 Touchscreen Driver | ||
| 3 | * | 2 | * |
| 4 | * (C) 2010 Luotao Fu <l.fu@pengutronix.de> | 3 | * (C) 2010 Luotao Fu <l.fu@pengutronix.de> |
| 5 | * All rights reserved. | 4 | * All rights reserved. |
| @@ -17,7 +16,6 @@ | |||
| 17 | #include <linux/interrupt.h> | 16 | #include <linux/interrupt.h> |
| 18 | #include <linux/init.h> | 17 | #include <linux/init.h> |
| 19 | #include <linux/device.h> | 18 | #include <linux/device.h> |
| 20 | #include <linux/of.h> | ||
| 21 | #include <linux/platform_device.h> | 19 | #include <linux/platform_device.h> |
| 22 | #include <linux/input.h> | 20 | #include <linux/input.h> |
| 23 | #include <linux/slab.h> | 21 | #include <linux/slab.h> |
| @@ -168,7 +166,7 @@ static irqreturn_t stmpe_ts_handler(int irq, void *data) | |||
| 168 | return IRQ_HANDLED; | 166 | return IRQ_HANDLED; |
| 169 | } | 167 | } |
| 170 | 168 | ||
| 171 | static int stmpe_init_hw(struct stmpe_touch *ts) | 169 | static int __devinit stmpe_init_hw(struct stmpe_touch *ts) |
| 172 | { | 170 | { |
| 173 | int ret; | 171 | int ret; |
| 174 | u8 adc_ctrl1, adc_ctrl1_mask, tsc_cfg, tsc_cfg_mask; | 172 | u8 adc_ctrl1, adc_ctrl1_mask, tsc_cfg, tsc_cfg_mask; |
| @@ -263,18 +261,41 @@ static void stmpe_ts_close(struct input_dev *dev) | |||
| 263 | STMPE_TSC_CTRL_TSC_EN, 0); | 261 | STMPE_TSC_CTRL_TSC_EN, 0); |
| 264 | } | 262 | } |
| 265 | 263 | ||
| 266 | static void stmpe_ts_get_platform_info(struct platform_device *pdev, | 264 | static int __devinit stmpe_input_probe(struct platform_device *pdev) |
| 267 | struct stmpe_touch *ts) | ||
| 268 | { | 265 | { |
| 269 | struct stmpe *stmpe = dev_get_drvdata(pdev->dev.parent); | 266 | struct stmpe *stmpe = dev_get_drvdata(pdev->dev.parent); |
| 270 | struct device_node *np = pdev->dev.of_node; | 267 | struct stmpe_platform_data *pdata = stmpe->pdata; |
| 268 | struct stmpe_touch *ts; | ||
| 269 | struct input_dev *idev; | ||
| 271 | struct stmpe_ts_platform_data *ts_pdata = NULL; | 270 | struct stmpe_ts_platform_data *ts_pdata = NULL; |
| 271 | int ret; | ||
| 272 | int ts_irq; | ||
| 273 | |||
| 274 | ts_irq = platform_get_irq_byname(pdev, "FIFO_TH"); | ||
| 275 | if (ts_irq < 0) | ||
| 276 | return ts_irq; | ||
| 277 | |||
| 278 | ts = kzalloc(sizeof(*ts), GFP_KERNEL); | ||
| 279 | if (!ts) { | ||
| 280 | ret = -ENOMEM; | ||
| 281 | goto err_out; | ||
| 282 | } | ||
| 283 | |||
| 284 | idev = input_allocate_device(); | ||
| 285 | if (!idev) { | ||
| 286 | ret = -ENOMEM; | ||
| 287 | goto err_free_ts; | ||
| 288 | } | ||
| 272 | 289 | ||
| 290 | platform_set_drvdata(pdev, ts); | ||
| 273 | ts->stmpe = stmpe; | 291 | ts->stmpe = stmpe; |
| 292 | ts->idev = idev; | ||
| 293 | ts->dev = &pdev->dev; | ||
| 274 | 294 | ||
| 275 | if (stmpe->pdata && stmpe->pdata->ts) { | 295 | if (pdata) |
| 276 | ts_pdata = stmpe->pdata->ts; | 296 | ts_pdata = pdata->ts; |
| 277 | 297 | ||
| 298 | if (ts_pdata) { | ||
| 278 | ts->sample_time = ts_pdata->sample_time; | 299 | ts->sample_time = ts_pdata->sample_time; |
| 279 | ts->mod_12b = ts_pdata->mod_12b; | 300 | ts->mod_12b = ts_pdata->mod_12b; |
| 280 | ts->ref_sel = ts_pdata->ref_sel; | 301 | ts->ref_sel = ts_pdata->ref_sel; |
| @@ -284,71 +305,22 @@ static void stmpe_ts_get_platform_info(struct platform_device *pdev, | |||
| 284 | ts->settling = ts_pdata->settling; | 305 | ts->settling = ts_pdata->settling; |
| 285 | ts->fraction_z = ts_pdata->fraction_z; | 306 | ts->fraction_z = ts_pdata->fraction_z; |
| 286 | ts->i_drive = ts_pdata->i_drive; | 307 | ts->i_drive = ts_pdata->i_drive; |
| 287 | } else if (np) { | ||
| 288 | u32 val; | ||
| 289 | |||
| 290 | if (!of_property_read_u32(np, "st,sample-time", &val)) | ||
| 291 | ts->sample_time = val; | ||
| 292 | if (!of_property_read_u32(np, "st,mod-12b", &val)) | ||
| 293 | ts->mod_12b = val; | ||
| 294 | if (!of_property_read_u32(np, "st,ref-sel", &val)) | ||
| 295 | ts->ref_sel = val; | ||
| 296 | if (!of_property_read_u32(np, "st,adc-freq", &val)) | ||
| 297 | ts->adc_freq = val; | ||
| 298 | if (!of_property_read_u32(np, "st,ave-ctrl", &val)) | ||
| 299 | ts->ave_ctrl = val; | ||
| 300 | if (!of_property_read_u32(np, "st,touch-det-delay", &val)) | ||
| 301 | ts->touch_det_delay = val; | ||
| 302 | if (!of_property_read_u32(np, "st,settling", &val)) | ||
| 303 | ts->settling = val; | ||
| 304 | if (!of_property_read_u32(np, "st,fraction-z", &val)) | ||
| 305 | ts->fraction_z = val; | ||
| 306 | if (!of_property_read_u32(np, "st,i-drive", &val)) | ||
| 307 | ts->i_drive = val; | ||
| 308 | } | 308 | } |
| 309 | } | ||
| 310 | |||
| 311 | static int stmpe_input_probe(struct platform_device *pdev) | ||
| 312 | { | ||
| 313 | struct stmpe_touch *ts; | ||
| 314 | struct input_dev *idev; | ||
| 315 | int error; | ||
| 316 | int ts_irq; | ||
| 317 | |||
| 318 | ts_irq = platform_get_irq_byname(pdev, "FIFO_TH"); | ||
| 319 | if (ts_irq < 0) | ||
| 320 | return ts_irq; | ||
| 321 | |||
| 322 | ts = devm_kzalloc(&pdev->dev, sizeof(*ts), GFP_KERNEL); | ||
| 323 | if (!ts) | ||
| 324 | return -ENOMEM; | ||
| 325 | |||
| 326 | idev = devm_input_allocate_device(&pdev->dev); | ||
| 327 | if (!idev) | ||
| 328 | return -ENOMEM; | ||
| 329 | |||
| 330 | platform_set_drvdata(pdev, ts); | ||
| 331 | ts->idev = idev; | ||
| 332 | ts->dev = &pdev->dev; | ||
| 333 | |||
| 334 | stmpe_ts_get_platform_info(pdev, ts); | ||
| 335 | 309 | ||
| 336 | INIT_DELAYED_WORK(&ts->work, stmpe_work); | 310 | INIT_DELAYED_WORK(&ts->work, stmpe_work); |
| 337 | 311 | ||
| 338 | error = devm_request_threaded_irq(&pdev->dev, ts_irq, | 312 | ret = request_threaded_irq(ts_irq, NULL, stmpe_ts_handler, |
| 339 | NULL, stmpe_ts_handler, | 313 | IRQF_ONESHOT, STMPE_TS_NAME, ts); |
| 340 | IRQF_ONESHOT, STMPE_TS_NAME, ts); | 314 | if (ret) { |
| 341 | if (error) { | ||
| 342 | dev_err(&pdev->dev, "Failed to request IRQ %d\n", ts_irq); | 315 | dev_err(&pdev->dev, "Failed to request IRQ %d\n", ts_irq); |
| 343 | return error; | 316 | goto err_free_input; |
| 344 | } | 317 | } |
| 345 | 318 | ||
| 346 | error = stmpe_init_hw(ts); | 319 | ret = stmpe_init_hw(ts); |
| 347 | if (error) | 320 | if (ret) |
| 348 | return error; | 321 | goto err_free_irq; |
| 349 | 322 | ||
| 350 | idev->name = STMPE_TS_NAME; | 323 | idev->name = STMPE_TS_NAME; |
| 351 | idev->phys = STMPE_TS_NAME"/input0"; | ||
| 352 | idev->id.bustype = BUS_I2C; | 324 | idev->id.bustype = BUS_I2C; |
| 353 | idev->evbit[0] = BIT_MASK(EV_KEY) | BIT_MASK(EV_ABS); | 325 | idev->evbit[0] = BIT_MASK(EV_KEY) | BIT_MASK(EV_ABS); |
| 354 | idev->keybit[BIT_WORD(BTN_TOUCH)] = BIT_MASK(BTN_TOUCH); | 326 | idev->keybit[BIT_WORD(BTN_TOUCH)] = BIT_MASK(BTN_TOUCH); |
| @@ -362,21 +334,40 @@ static int stmpe_input_probe(struct platform_device *pdev) | |||
| 362 | input_set_abs_params(idev, ABS_Y, 0, XY_MASK, 0, 0); | 334 | input_set_abs_params(idev, ABS_Y, 0, XY_MASK, 0, 0); |
| 363 | input_set_abs_params(idev, ABS_PRESSURE, 0x0, 0xff, 0, 0); | 335 | input_set_abs_params(idev, ABS_PRESSURE, 0x0, 0xff, 0, 0); |
| 364 | 336 | ||
| 365 | error = input_register_device(idev); | 337 | ret = input_register_device(idev); |
| 366 | if (error) { | 338 | if (ret) { |
| 367 | dev_err(&pdev->dev, "Could not register input device\n"); | 339 | dev_err(&pdev->dev, "Could not register input device\n"); |
| 368 | return error; | 340 | goto err_free_irq; |
| 369 | } | 341 | } |
| 370 | 342 | ||
| 371 | return 0; | 343 | return ret; |
| 344 | |||
| 345 | err_free_irq: | ||
| 346 | free_irq(ts_irq, ts); | ||
| 347 | err_free_input: | ||
| 348 | input_free_device(idev); | ||
| 349 | platform_set_drvdata(pdev, NULL); | ||
| 350 | err_free_ts: | ||
| 351 | kfree(ts); | ||
| 352 | err_out: | ||
| 353 | return ret; | ||
| 372 | } | 354 | } |
| 373 | 355 | ||
| 374 | static int stmpe_ts_remove(struct platform_device *pdev) | 356 | static int __devexit stmpe_ts_remove(struct platform_device *pdev) |
| 375 | { | 357 | { |
| 376 | struct stmpe_touch *ts = platform_get_drvdata(pdev); | 358 | struct stmpe_touch *ts = platform_get_drvdata(pdev); |
| 359 | unsigned int ts_irq = platform_get_irq_byname(pdev, "FIFO_TH"); | ||
| 377 | 360 | ||
| 378 | stmpe_disable(ts->stmpe, STMPE_BLOCK_TOUCHSCREEN); | 361 | stmpe_disable(ts->stmpe, STMPE_BLOCK_TOUCHSCREEN); |
| 379 | 362 | ||
| 363 | free_irq(ts_irq, ts); | ||
| 364 | |||
| 365 | platform_set_drvdata(pdev, NULL); | ||
| 366 | |||
| 367 | input_unregister_device(ts->idev); | ||
| 368 | |||
| 369 | kfree(ts); | ||
| 370 | |||
| 380 | return 0; | 371 | return 0; |
| 381 | } | 372 | } |
| 382 | 373 | ||
| @@ -386,9 +377,22 @@ static struct platform_driver stmpe_ts_driver = { | |||
| 386 | .owner = THIS_MODULE, | 377 | .owner = THIS_MODULE, |
| 387 | }, | 378 | }, |
| 388 | .probe = stmpe_input_probe, | 379 | .probe = stmpe_input_probe, |
| 389 | .remove = stmpe_ts_remove, | 380 | .remove = __devexit_p(stmpe_ts_remove), |
| 390 | }; | 381 | }; |
| 391 | module_platform_driver(stmpe_ts_driver); | 382 | |
| 383 | static int __init stmpe_ts_init(void) | ||
| 384 | { | ||
| 385 | return platform_driver_register(&stmpe_ts_driver); | ||
| 386 | } | ||
| 387 | |||
| 388 | module_init(stmpe_ts_init); | ||
| 389 | |||
| 390 | static void __exit stmpe_ts_exit(void) | ||
| 391 | { | ||
| 392 | platform_driver_unregister(&stmpe_ts_driver); | ||
| 393 | } | ||
| 394 | |||
| 395 | module_exit(stmpe_ts_exit); | ||
| 392 | 396 | ||
| 393 | MODULE_AUTHOR("Luotao Fu <l.fu@pengutronix.de>"); | 397 | MODULE_AUTHOR("Luotao Fu <l.fu@pengutronix.de>"); |
| 394 | MODULE_DESCRIPTION("STMPEXXX touchscreen driver"); | 398 | MODULE_DESCRIPTION("STMPEXXX touchscreen driver"); |
diff --git a/drivers/input/touchscreen/ti_am335x_tsc.c b/drivers/input/touchscreen/ti_am335x_tsc.c deleted file mode 100644 index 51e7b87827a..00000000000 --- a/drivers/input/touchscreen/ti_am335x_tsc.c +++ /dev/null | |||
| @@ -1,398 +0,0 @@ | |||
| 1 | /* | ||
| 2 | * TI Touch Screen driver | ||
| 3 | * | ||
| 4 | * Copyright (C) 2011 Texas Instruments Incorporated - http://www.ti.com/ | ||
| 5 | * | ||
| 6 | * This program is free software; you can redistribute it and/or | ||
| 7 | * modify it under the terms of the GNU General Public License as | ||
| 8 | * published by the Free Software Foundation version 2. | ||
| 9 | * | ||
| 10 | * This program is distributed "as is" WITHOUT ANY WARRANTY of any | ||
| 11 | * kind, whether express or implied; without even the implied warranty | ||
| 12 | * of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the | ||
| 13 | * GNU General Public License for more details. | ||
| 14 | */ | ||
| 15 | |||
| 16 | |||
| 17 | #include <linux/init.h> | ||
| 18 | #include <linux/kernel.h> | ||
| 19 | #include <linux/err.h> | ||
| 20 | #include <linux/module.h> | ||
| 21 | #include <linux/input.h> | ||
| 22 | #include <linux/slab.h> | ||
| 23 | #include <linux/interrupt.h> | ||
| 24 | #include <linux/clk.h> | ||
| 25 | #include <linux/platform_device.h> | ||
| 26 | #include <linux/io.h> | ||
| 27 | #include <linux/input/ti_am335x_tsc.h> | ||
| 28 | #include <linux/delay.h> | ||
| 29 | |||
| 30 | #include <linux/mfd/ti_am335x_tscadc.h> | ||
| 31 | |||
| 32 | #define ADCFSM_STEPID 0x10 | ||
| 33 | #define SEQ_SETTLE 275 | ||
| 34 | #define MAX_12BIT ((1 << 12) - 1) | ||
| 35 | |||
| 36 | struct titsc { | ||
| 37 | struct input_dev *input; | ||
| 38 | struct ti_tscadc_dev *mfd_tscadc; | ||
| 39 | unsigned int irq; | ||
| 40 | unsigned int wires; | ||
| 41 | unsigned int x_plate_resistance; | ||
| 42 | bool pen_down; | ||
| 43 | int steps_to_configure; | ||
| 44 | }; | ||
| 45 | |||
| 46 | static unsigned int titsc_readl(struct titsc *ts, unsigned int reg) | ||
| 47 | { | ||
| 48 | return readl(ts->mfd_tscadc->tscadc_base + reg); | ||
| 49 | } | ||
| 50 | |||
| 51 | static void titsc_writel(struct titsc *tsc, unsigned int reg, | ||
| 52 | unsigned int val) | ||
| 53 | { | ||
| 54 | writel(val, tsc->mfd_tscadc->tscadc_base + reg); | ||
| 55 | } | ||
| 56 | |||
| 57 | static void titsc_step_config(struct titsc *ts_dev) | ||
| 58 | { | ||
| 59 | unsigned int config; | ||
| 60 | int i, total_steps; | ||
| 61 | |||
| 62 | /* Configure the Step registers */ | ||
| 63 | total_steps = 2 * ts_dev->steps_to_configure; | ||
| 64 | |||
| 65 | config = STEPCONFIG_MODE_HWSYNC | | ||
| 66 | STEPCONFIG_AVG_16 | STEPCONFIG_XPP; | ||
| 67 | switch (ts_dev->wires) { | ||
| 68 | case 4: | ||
| 69 | config |= STEPCONFIG_INP_AN2 | STEPCONFIG_XNN; | ||
| 70 | break; | ||
| 71 | case 5: | ||
| 72 | config |= STEPCONFIG_YNN | | ||
| 73 | STEPCONFIG_INP_AN4 | STEPCONFIG_XNN | | ||
| 74 | STEPCONFIG_YPP; | ||
| 75 | break; | ||
| 76 | case 8: | ||
| 77 | config |= STEPCONFIG_INP_AN2 | STEPCONFIG_XNN; | ||
| 78 | break; | ||
| 79 | } | ||
| 80 | |||
| 81 | for (i = 1; i <= ts_dev->steps_to_configure; i++) { | ||
| 82 | titsc_writel(ts_dev, REG_STEPCONFIG(i), config); | ||
| 83 | titsc_writel(ts_dev, REG_STEPDELAY(i), STEPCONFIG_OPENDLY); | ||
| 84 | } | ||
| 85 | |||
| 86 | config = 0; | ||
| 87 | config = STEPCONFIG_MODE_HWSYNC | | ||
| 88 | STEPCONFIG_AVG_16 | STEPCONFIG_YNN | | ||
| 89 | STEPCONFIG_INM_ADCREFM | STEPCONFIG_FIFO1; | ||
| 90 | switch (ts_dev->wires) { | ||
| 91 | case 4: | ||
| 92 | config |= STEPCONFIG_YPP; | ||
| 93 | break; | ||
| 94 | case 5: | ||
| 95 | config |= STEPCONFIG_XPP | STEPCONFIG_INP_AN4 | | ||
| 96 | STEPCONFIG_XNP | STEPCONFIG_YPN; | ||
| 97 | break; | ||
| 98 | case 8: | ||
| 99 | config |= STEPCONFIG_YPP; | ||
| 100 | break; | ||
| 101 | } | ||
| 102 | |||
| 103 | for (i = (ts_dev->steps_to_configure + 1); i <= total_steps; i++) { | ||
| 104 | titsc_writel(ts_dev, REG_STEPCONFIG(i), config); | ||
| 105 | titsc_writel(ts_dev, REG_STEPDELAY(i), STEPCONFIG_OPENDLY); | ||
| 106 | } | ||
| 107 | |||
| 108 | config = 0; | ||
| 109 | /* Charge step configuration */ | ||
| 110 | config = STEPCONFIG_XPP | STEPCONFIG_YNN | | ||
| 111 | STEPCHARGE_RFP_XPUL | STEPCHARGE_RFM_XNUR | | ||
| 112 | STEPCHARGE_INM_AN1 | STEPCHARGE_INP_AN1; | ||
| 113 | |||
| 114 | titsc_writel(ts_dev, REG_CHARGECONFIG, config); | ||
| 115 | titsc_writel(ts_dev, REG_CHARGEDELAY, CHARGEDLY_OPENDLY); | ||
| 116 | |||
| 117 | config = 0; | ||
| 118 | /* Configure to calculate pressure */ | ||
| 119 | config = STEPCONFIG_MODE_HWSYNC | | ||
| 120 | STEPCONFIG_AVG_16 | STEPCONFIG_YPP | | ||
| 121 | STEPCONFIG_XNN | STEPCONFIG_INM_ADCREFM; | ||
| 122 | titsc_writel(ts_dev, REG_STEPCONFIG(total_steps + 1), config); | ||
| 123 | titsc_writel(ts_dev, REG_STEPDELAY(total_steps + 1), | ||
| 124 | STEPCONFIG_OPENDLY); | ||
| 125 | |||
| 126 | config |= STEPCONFIG_INP_AN3 | STEPCONFIG_FIFO1; | ||
| 127 | titsc_writel(ts_dev, REG_STEPCONFIG(total_steps + 2), config); | ||
| 128 | titsc_writel(ts_dev, REG_STEPDELAY(total_steps + 2), | ||
| 129 | STEPCONFIG_OPENDLY); | ||
| 130 | |||
| 131 | titsc_writel(ts_dev, REG_SE, STPENB_STEPENB_TC); | ||
| 132 | } | ||
| 133 | |||
| 134 | static void titsc_read_coordinates(struct titsc *ts_dev, | ||
| 135 | unsigned int *x, unsigned int *y) | ||
| 136 | { | ||
| 137 | unsigned int fifocount = titsc_readl(ts_dev, REG_FIFO0CNT); | ||
| 138 | unsigned int prev_val_x = ~0, prev_val_y = ~0; | ||
| 139 | unsigned int prev_diff_x = ~0, prev_diff_y = ~0; | ||
| 140 | unsigned int read, diff; | ||
| 141 | unsigned int i, channel; | ||
| 142 | |||
| 143 | /* | ||
| 144 | * Delta filter is used to remove large variations in sampled | ||
| 145 | * values from ADC. The filter tries to predict where the next | ||
| 146 | * coordinate could be. This is done by taking a previous | ||
| 147 | * coordinate and subtracting it form current one. Further the | ||
| 148 | * algorithm compares the difference with that of a present value, | ||
| 149 | * if true the value is reported to the sub system. | ||
| 150 | */ | ||
| 151 | for (i = 0; i < fifocount - 1; i++) { | ||
| 152 | read = titsc_readl(ts_dev, REG_FIFO0); | ||
| 153 | channel = read & 0xf0000; | ||
| 154 | channel = channel >> 0x10; | ||
| 155 | if ((channel >= 0) && (channel < ts_dev->steps_to_configure)) { | ||
| 156 | read &= 0xfff; | ||
| 157 | diff = abs(read - prev_val_x); | ||
| 158 | if (diff < prev_diff_x) { | ||
| 159 | prev_diff_x = diff; | ||
| 160 | *x = read; | ||
| 161 | } | ||
| 162 | prev_val_x = read; | ||
| 163 | } | ||
| 164 | |||
| 165 | read = titsc_readl(ts_dev, REG_FIFO1); | ||
| 166 | channel = read & 0xf0000; | ||
| 167 | channel = channel >> 0x10; | ||
| 168 | if ((channel >= ts_dev->steps_to_configure) && | ||
| 169 | (channel < (2 * ts_dev->steps_to_configure - 1))) { | ||
| 170 | read &= 0xfff; | ||
| 171 | diff = abs(read - prev_val_y); | ||
| 172 | if (diff < prev_diff_y) { | ||
| 173 | prev_diff_y = diff; | ||
| 174 | *y = read; | ||
| 175 | } | ||
| 176 | prev_val_y = read; | ||
| 177 | } | ||
| 178 | } | ||
| 179 | } | ||
| 180 | |||
| 181 | static irqreturn_t titsc_irq(int irq, void *dev) | ||
| 182 | { | ||
| 183 | struct titsc *ts_dev = dev; | ||
| 184 | struct input_dev *input_dev = ts_dev->input; | ||
| 185 | unsigned int status, irqclr = 0; | ||
| 186 | unsigned int x = 0, y = 0; | ||
| 187 | unsigned int z1, z2, z; | ||
| 188 | unsigned int fsm; | ||
| 189 | unsigned int fifo1count, fifo0count; | ||
| 190 | int i; | ||
| 191 | |||
| 192 | status = titsc_readl(ts_dev, REG_IRQSTATUS); | ||
| 193 | if (status & IRQENB_FIFO0THRES) { | ||
| 194 | titsc_read_coordinates(ts_dev, &x, &y); | ||
| 195 | |||
| 196 | z1 = titsc_readl(ts_dev, REG_FIFO0) & 0xfff; | ||
| 197 | z2 = titsc_readl(ts_dev, REG_FIFO1) & 0xfff; | ||
| 198 | |||
| 199 | fifo1count = titsc_readl(ts_dev, REG_FIFO1CNT); | ||
| 200 | for (i = 0; i < fifo1count; i++) | ||
| 201 | titsc_readl(ts_dev, REG_FIFO1); | ||
| 202 | |||
| 203 | fifo0count = titsc_readl(ts_dev, REG_FIFO0CNT); | ||
| 204 | for (i = 0; i < fifo0count; i++) | ||
| 205 | titsc_readl(ts_dev, REG_FIFO0); | ||
| 206 | |||
| 207 | if (ts_dev->pen_down && z1 != 0 && z2 != 0) { | ||
| 208 | /* | ||
| 209 | * Calculate pressure using formula | ||
| 210 | * Resistance(touch) = x plate resistance * | ||
| 211 | * x postion/4096 * ((z2 / z1) - 1) | ||
| 212 | */ | ||
| 213 | z = z2 - z1; | ||
| 214 | z *= x; | ||
| 215 | z *= ts_dev->x_plate_resistance; | ||
| 216 | z /= z1; | ||
| 217 | z = (z + 2047) >> 12; | ||
| 218 | |||
| 219 | if (z <= MAX_12BIT) { | ||
| 220 | input_report_abs(input_dev, ABS_X, x); | ||
| 221 | input_report_abs(input_dev, ABS_Y, y); | ||
| 222 | input_report_abs(input_dev, ABS_PRESSURE, z); | ||
| 223 | input_report_key(input_dev, BTN_TOUCH, 1); | ||
| 224 | input_sync(input_dev); | ||
| 225 | } | ||
| 226 | } | ||
| 227 | irqclr |= IRQENB_FIFO0THRES; | ||
| 228 | } | ||
| 229 | |||
| 230 | /* | ||
| 231 | * Time for sequencer to settle, to read | ||
| 232 | * correct state of the sequencer. | ||
| 233 | */ | ||
| 234 | udelay(SEQ_SETTLE); | ||
| 235 | |||
| 236 | status = titsc_readl(ts_dev, REG_RAWIRQSTATUS); | ||
| 237 | if (status & IRQENB_PENUP) { | ||
| 238 | /* Pen up event */ | ||
| 239 | fsm = titsc_readl(ts_dev, REG_ADCFSM); | ||
| 240 | if (fsm == ADCFSM_STEPID) { | ||
| 241 | ts_dev->pen_down = false; | ||
| 242 | input_report_key(input_dev, BTN_TOUCH, 0); | ||
| 243 | input_report_abs(input_dev, ABS_PRESSURE, 0); | ||
| 244 | input_sync(input_dev); | ||
| 245 | } else { | ||
| 246 | ts_dev->pen_down = true; | ||
| 247 | } | ||
| 248 | irqclr |= IRQENB_PENUP; | ||
| 249 | } | ||
| 250 | |||
| 251 | titsc_writel(ts_dev, REG_IRQSTATUS, irqclr); | ||
| 252 | |||
| 253 | titsc_writel(ts_dev, REG_SE, STPENB_STEPENB_TC); | ||
| 254 | return IRQ_HANDLED; | ||
| 255 | } | ||
| 256 | |||
| 257 | /* | ||
| 258 | * The functions for inserting/removing driver as a module. | ||
| 259 | */ | ||
| 260 | |||
| 261 | static int titsc_probe(struct platform_device *pdev) | ||
| 262 | { | ||
| 263 | struct titsc *ts_dev; | ||
| 264 | struct input_dev *input_dev; | ||
| 265 | struct ti_tscadc_dev *tscadc_dev = pdev->dev.platform_data; | ||
| 266 | struct mfd_tscadc_board *pdata; | ||
| 267 | int err; | ||
| 268 | |||
| 269 | pdata = tscadc_dev->dev->platform_data; | ||
| 270 | |||
| 271 | if (!pdata) { | ||
| 272 | dev_err(&pdev->dev, "Could not find platform data\n"); | ||
| 273 | return -EINVAL; | ||
| 274 | } | ||
| 275 | |||
| 276 | /* Allocate memory for device */ | ||
| 277 | ts_dev = kzalloc(sizeof(struct titsc), GFP_KERNEL); | ||
| 278 | input_dev = input_allocate_device(); | ||
| 279 | if (!ts_dev || !input_dev) { | ||
| 280 | dev_err(&pdev->dev, "failed to allocate memory.\n"); | ||
| 281 | err = -ENOMEM; | ||
| 282 | goto err_free_mem; | ||
| 283 | } | ||
| 284 | |||
| 285 | tscadc_dev->tsc = ts_dev; | ||
| 286 | ts_dev->mfd_tscadc = tscadc_dev; | ||
| 287 | ts_dev->input = input_dev; | ||
| 288 | ts_dev->irq = tscadc_dev->irq; | ||
| 289 | ts_dev->wires = pdata->tsc_init->wires; | ||
| 290 | ts_dev->x_plate_resistance = pdata->tsc_init->x_plate_resistance; | ||
| 291 | ts_dev->steps_to_configure = pdata->tsc_init->steps_to_configure; | ||
| 292 | |||
| 293 | err = request_irq(ts_dev->irq, titsc_irq, | ||
| 294 | 0, pdev->dev.driver->name, ts_dev); | ||
| 295 | if (err) { | ||
| 296 | dev_err(&pdev->dev, "failed to allocate irq.\n"); | ||
| 297 | goto err_free_mem; | ||
| 298 | } | ||
| 299 | |||
| 300 | titsc_writel(ts_dev, REG_IRQENABLE, IRQENB_FIFO0THRES); | ||
| 301 | titsc_step_config(ts_dev); | ||
| 302 | titsc_writel(ts_dev, REG_FIFO0THR, ts_dev->steps_to_configure); | ||
| 303 | |||
| 304 | input_dev->name = "ti-tsc"; | ||
| 305 | input_dev->dev.parent = &pdev->dev; | ||
| 306 | |||
| 307 | input_dev->evbit[0] = BIT_MASK(EV_KEY) | BIT_MASK(EV_ABS); | ||
| 308 | input_dev->keybit[BIT_WORD(BTN_TOUCH)] = BIT_MASK(BTN_TOUCH); | ||
| 309 | |||
| 310 | input_set_abs_params(input_dev, ABS_X, 0, MAX_12BIT, 0, 0); | ||
| 311 | input_set_abs_params(input_dev, ABS_Y, 0, MAX_12BIT, 0, 0); | ||
| 312 | input_set_abs_params(input_dev, ABS_PRESSURE, 0, MAX_12BIT, 0, 0); | ||
| 313 | |||
| 314 | /* register to the input system */ | ||
| 315 | err = input_register_device(input_dev); | ||
| 316 | if (err) | ||
| 317 | goto err_free_irq; | ||
| 318 | |||
| 319 | platform_set_drvdata(pdev, ts_dev); | ||
| 320 | return 0; | ||
| 321 | |||
| 322 | err_free_irq: | ||
| 323 | free_irq(ts_dev->irq, ts_dev); | ||
| 324 | err_free_mem: | ||
| 325 | input_free_device(input_dev); | ||
| 326 | kfree(ts_dev); | ||
| 327 | return err; | ||
| 328 | } | ||
| 329 | |||
| 330 | static int titsc_remove(struct platform_device *pdev) | ||
| 331 | { | ||
| 332 | struct ti_tscadc_dev *tscadc_dev = pdev->dev.platform_data; | ||
| 333 | struct titsc *ts_dev = tscadc_dev->tsc; | ||
| 334 | |||
| 335 | free_irq(ts_dev->irq, ts_dev); | ||
| 336 | |||
| 337 | input_unregister_device(ts_dev->input); | ||
| 338 | |||
| 339 | platform_set_drvdata(pdev, NULL); | ||
| 340 | kfree(ts_dev); | ||
| 341 | return 0; | ||
| 342 | } | ||
| 343 | |||
| 344 | #ifdef CONFIG_PM | ||
| 345 | static int titsc_suspend(struct device *dev) | ||
| 346 | { | ||
| 347 | struct ti_tscadc_dev *tscadc_dev = dev->platform_data; | ||
| 348 | struct titsc *ts_dev = tscadc_dev->tsc; | ||
| 349 | unsigned int idle; | ||
| 350 | |||
| 351 | if (device_may_wakeup(tscadc_dev->dev)) { | ||
| 352 | idle = titsc_readl(ts_dev, REG_IRQENABLE); | ||
| 353 | titsc_writel(ts_dev, REG_IRQENABLE, | ||
| 354 | (idle | IRQENB_HW_PEN)); | ||
| 355 | titsc_writel(ts_dev, REG_IRQWAKEUP, IRQWKUP_ENB); | ||
| 356 | } | ||
| 357 | return 0; | ||
| 358 | } | ||
| 359 | |||
| 360 | static int titsc_resume(struct device *dev) | ||
| 361 | { | ||
| 362 | struct ti_tscadc_dev *tscadc_dev = dev->platform_data; | ||
| 363 | struct titsc *ts_dev = tscadc_dev->tsc; | ||
| 364 | |||
| 365 | if (device_may_wakeup(tscadc_dev->dev)) { | ||
| 366 | titsc_writel(ts_dev, REG_IRQWAKEUP, | ||
| 367 | 0x00); | ||
| 368 | titsc_writel(ts_dev, REG_IRQCLR, IRQENB_HW_PEN); | ||
| 369 | } | ||
| 370 | titsc_step_config(ts_dev); | ||
| 371 | titsc_writel(ts_dev, REG_FIFO0THR, | ||
| 372 | ts_dev->steps_to_configure); | ||
| 373 | return 0; | ||
| 374 | } | ||
| 375 | |||
| 376 | static const struct dev_pm_ops titsc_pm_ops = { | ||
| 377 | .suspend = titsc_suspend, | ||
| 378 | .resume = titsc_resume, | ||
| 379 | }; | ||
| 380 | #define TITSC_PM_OPS (&titsc_pm_ops) | ||
| 381 | #else | ||
| 382 | #define TITSC_PM_OPS NULL | ||
| 383 | #endif | ||
| 384 | |||
| 385 | static struct platform_driver ti_tsc_driver = { | ||
| 386 | .probe = titsc_probe, | ||
| 387 | .remove = titsc_remove, | ||
| 388 | .driver = { | ||
| 389 | .name = "tsc", | ||
| 390 | .owner = THIS_MODULE, | ||
| 391 | .pm = TITSC_PM_OPS, | ||
| 392 | }, | ||
| 393 | }; | ||
| 394 | module_platform_driver(ti_tsc_driver); | ||
| 395 | |||
| 396 | MODULE_DESCRIPTION("TI touchscreen controller driver"); | ||
| 397 | MODULE_AUTHOR("Rachna Patil <rachna@ti.com>"); | ||
| 398 | MODULE_LICENSE("GPL"); | ||
diff --git a/drivers/input/touchscreen/tnetv107x-ts.c b/drivers/input/touchscreen/tnetv107x-ts.c index acfb87607b8..0e8f63e5b36 100644 --- a/drivers/input/touchscreen/tnetv107x-ts.c +++ b/drivers/input/touchscreen/tnetv107x-ts.c | |||
| @@ -243,7 +243,7 @@ static void tsc_stop(struct input_dev *dev) | |||
| 243 | clk_disable(ts->clk); | 243 | clk_disable(ts->clk); |
| 244 | } | 244 | } |
| 245 | 245 | ||
| 246 | static int tsc_probe(struct platform_device *pdev) | 246 | static int __devinit tsc_probe(struct platform_device *pdev) |
| 247 | { | 247 | { |
| 248 | struct device *dev = &pdev->dev; | 248 | struct device *dev = &pdev->dev; |
| 249 | struct tsc_data *ts; | 249 | struct tsc_data *ts; |
| @@ -297,7 +297,7 @@ static int tsc_probe(struct platform_device *pdev) | |||
| 297 | goto error_clk; | 297 | goto error_clk; |
| 298 | } | 298 | } |
| 299 | 299 | ||
| 300 | error = request_threaded_irq(ts->tsc_irq, NULL, tsc_irq, IRQF_ONESHOT, | 300 | error = request_threaded_irq(ts->tsc_irq, NULL, tsc_irq, 0, |
| 301 | dev_name(dev), ts); | 301 | dev_name(dev), ts); |
| 302 | if (error < 0) { | 302 | if (error < 0) { |
| 303 | dev_err(ts->dev, "Could not allocate ts irq\n"); | 303 | dev_err(ts->dev, "Could not allocate ts irq\n"); |
| @@ -357,7 +357,7 @@ error_res: | |||
| 357 | return error; | 357 | return error; |
| 358 | } | 358 | } |
| 359 | 359 | ||
| 360 | static int tsc_remove(struct platform_device *pdev) | 360 | static int __devexit tsc_remove(struct platform_device *pdev) |
| 361 | { | 361 | { |
| 362 | struct tsc_data *ts = platform_get_drvdata(pdev); | 362 | struct tsc_data *ts = platform_get_drvdata(pdev); |
| 363 | 363 | ||
| @@ -374,11 +374,23 @@ static int tsc_remove(struct platform_device *pdev) | |||
| 374 | 374 | ||
| 375 | static struct platform_driver tsc_driver = { | 375 | static struct platform_driver tsc_driver = { |
| 376 | .probe = tsc_probe, | 376 | .probe = tsc_probe, |
| 377 | .remove = tsc_remove, | 377 | .remove = __devexit_p(tsc_remove), |
| 378 | .driver.name = "tnetv107x-ts", | 378 | .driver.name = "tnetv107x-ts", |
| 379 | .driver.owner = THIS_MODULE, | 379 | .driver.owner = THIS_MODULE, |
| 380 | }; | 380 | }; |
| 381 | module_platform_driver(tsc_driver); | 381 | |
| 382 | static int __init tsc_init(void) | ||
| 383 | { | ||
| 384 | return platform_driver_register(&tsc_driver); | ||
| 385 | } | ||
| 386 | |||
| 387 | static void __exit tsc_exit(void) | ||
| 388 | { | ||
| 389 | platform_driver_unregister(&tsc_driver); | ||
| 390 | } | ||
| 391 | |||
| 392 | module_init(tsc_init); | ||
| 393 | module_exit(tsc_exit); | ||
| 382 | 394 | ||
| 383 | MODULE_AUTHOR("Cyril Chemparathy"); | 395 | MODULE_AUTHOR("Cyril Chemparathy"); |
| 384 | MODULE_DESCRIPTION("TNETV107X Touchscreen Driver"); | 396 | MODULE_DESCRIPTION("TNETV107X Touchscreen Driver"); |
diff --git a/drivers/input/touchscreen/touchit213.c b/drivers/input/touchscreen/touchit213.c index 5f29e5b8e1c..d1297ba19da 100644 --- a/drivers/input/touchscreen/touchit213.c +++ b/drivers/input/touchscreen/touchit213.c | |||
| @@ -216,4 +216,19 @@ static struct serio_driver touchit213_drv = { | |||
| 216 | .disconnect = touchit213_disconnect, | 216 | .disconnect = touchit213_disconnect, |
| 217 | }; | 217 | }; |
| 218 | 218 | ||
| 219 | module_serio_driver(touchit213_drv); | 219 | /* |
| 220 | * The functions for inserting/removing us as a module. | ||
| 221 | */ | ||
| 222 | |||
| 223 | static int __init touchit213_init(void) | ||
| 224 | { | ||
| 225 | return serio_register_driver(&touchit213_drv); | ||
| 226 | } | ||
| 227 | |||
| 228 | static void __exit touchit213_exit(void) | ||
| 229 | { | ||
| 230 | serio_unregister_driver(&touchit213_drv); | ||
| 231 | } | ||
| 232 | |||
| 233 | module_init(touchit213_init); | ||
| 234 | module_exit(touchit213_exit); | ||
diff --git a/drivers/input/touchscreen/touchright.c b/drivers/input/touchscreen/touchright.c index 8a2887daf19..3a5c142c2a7 100644 --- a/drivers/input/touchscreen/touchright.c +++ b/drivers/input/touchscreen/touchright.c | |||
| @@ -176,4 +176,19 @@ static struct serio_driver tr_drv = { | |||
| 176 | .disconnect = tr_disconnect, | 176 | .disconnect = tr_disconnect, |
| 177 | }; | 177 | }; |
| 178 | 178 | ||
| 179 | module_serio_driver(tr_drv); | 179 | /* |
| 180 | * The functions for inserting/removing us as a module. | ||
| 181 | */ | ||
| 182 | |||
| 183 | static int __init tr_init(void) | ||
| 184 | { | ||
| 185 | return serio_register_driver(&tr_drv); | ||
| 186 | } | ||
| 187 | |||
| 188 | static void __exit tr_exit(void) | ||
| 189 | { | ||
| 190 | serio_unregister_driver(&tr_drv); | ||
| 191 | } | ||
| 192 | |||
| 193 | module_init(tr_init); | ||
| 194 | module_exit(tr_exit); | ||
diff --git a/drivers/input/touchscreen/touchwin.c b/drivers/input/touchscreen/touchwin.c index 588cdcb839d..763a656a59f 100644 --- a/drivers/input/touchscreen/touchwin.c +++ b/drivers/input/touchscreen/touchwin.c | |||
| @@ -183,4 +183,19 @@ static struct serio_driver tw_drv = { | |||
| 183 | .disconnect = tw_disconnect, | 183 | .disconnect = tw_disconnect, |
| 184 | }; | 184 | }; |
| 185 | 185 | ||
| 186 | module_serio_driver(tw_drv); | 186 | /* |
| 187 | * The functions for inserting/removing us as a module. | ||
| 188 | */ | ||
| 189 | |||
| 190 | static int __init tw_init(void) | ||
| 191 | { | ||
| 192 | return serio_register_driver(&tw_drv); | ||
| 193 | } | ||
| 194 | |||
| 195 | static void __exit tw_exit(void) | ||
| 196 | { | ||
| 197 | serio_unregister_driver(&tw_drv); | ||
| 198 | } | ||
| 199 | |||
| 200 | module_init(tw_init); | ||
| 201 | module_exit(tw_exit); | ||
diff --git a/drivers/input/touchscreen/tps6507x-ts.c b/drivers/input/touchscreen/tps6507x-ts.c index 820a066c3b8..43031492d73 100644 --- a/drivers/input/touchscreen/tps6507x-ts.c +++ b/drivers/input/touchscreen/tps6507x-ts.c | |||
| @@ -1,4 +1,6 @@ | |||
| 1 | /* | 1 | /* |
| 2 | * drivers/input/touchscreen/tps6507x_ts.c | ||
| 3 | * | ||
| 2 | * Touchscreen driver for the tps6507x chip. | 4 | * Touchscreen driver for the tps6507x chip. |
| 3 | * | 5 | * |
| 4 | * Copyright (c) 2009 RidgeRun (todd.fischer@ridgerun.com) | 6 | * Copyright (c) 2009 RidgeRun (todd.fischer@ridgerun.com) |
| @@ -345,7 +347,7 @@ err0: | |||
| 345 | return error; | 347 | return error; |
| 346 | } | 348 | } |
| 347 | 349 | ||
| 348 | static int tps6507x_ts_remove(struct platform_device *pdev) | 350 | static int __devexit tps6507x_ts_remove(struct platform_device *pdev) |
| 349 | { | 351 | { |
| 350 | struct tps6507x_dev *tps6507x_dev = platform_get_drvdata(pdev); | 352 | struct tps6507x_dev *tps6507x_dev = platform_get_drvdata(pdev); |
| 351 | struct tps6507x_ts *tsc = tps6507x_dev->ts; | 353 | struct tps6507x_ts *tsc = tps6507x_dev->ts; |
| @@ -367,11 +369,22 @@ static struct platform_driver tps6507x_ts_driver = { | |||
| 367 | .owner = THIS_MODULE, | 369 | .owner = THIS_MODULE, |
| 368 | }, | 370 | }, |
| 369 | .probe = tps6507x_ts_probe, | 371 | .probe = tps6507x_ts_probe, |
| 370 | .remove = tps6507x_ts_remove, | 372 | .remove = __devexit_p(tps6507x_ts_remove), |
| 371 | }; | 373 | }; |
| 372 | module_platform_driver(tps6507x_ts_driver); | 374 | |
| 375 | static int __init tps6507x_ts_init(void) | ||
| 376 | { | ||
| 377 | return platform_driver_register(&tps6507x_ts_driver); | ||
| 378 | } | ||
| 379 | module_init(tps6507x_ts_init); | ||
| 380 | |||
| 381 | static void __exit tps6507x_ts_exit(void) | ||
| 382 | { | ||
| 383 | platform_driver_unregister(&tps6507x_ts_driver); | ||
| 384 | } | ||
| 385 | module_exit(tps6507x_ts_exit); | ||
| 373 | 386 | ||
| 374 | MODULE_AUTHOR("Todd Fischer <todd.fischer@ridgerun.com>"); | 387 | MODULE_AUTHOR("Todd Fischer <todd.fischer@ridgerun.com>"); |
| 375 | MODULE_DESCRIPTION("TPS6507x - TouchScreen driver"); | 388 | MODULE_DESCRIPTION("TPS6507x - TouchScreen driver"); |
| 376 | MODULE_LICENSE("GPL v2"); | 389 | MODULE_LICENSE("GPL v2"); |
| 377 | MODULE_ALIAS("platform:tps6507x-ts"); | 390 | MODULE_ALIAS("platform:tps6507x-tsc"); |
diff --git a/drivers/input/touchscreen/tsc2005.c b/drivers/input/touchscreen/tsc2005.c index 9c0cdc7ea44..cbf0ff32267 100644 --- a/drivers/input/touchscreen/tsc2005.c +++ b/drivers/input/touchscreen/tsc2005.c | |||
| @@ -450,13 +450,13 @@ static struct attribute *tsc2005_attrs[] = { | |||
| 450 | NULL | 450 | NULL |
| 451 | }; | 451 | }; |
| 452 | 452 | ||
| 453 | static umode_t tsc2005_attr_is_visible(struct kobject *kobj, | 453 | static mode_t tsc2005_attr_is_visible(struct kobject *kobj, |
| 454 | struct attribute *attr, int n) | 454 | struct attribute *attr, int n) |
| 455 | { | 455 | { |
| 456 | struct device *dev = container_of(kobj, struct device, kobj); | 456 | struct device *dev = container_of(kobj, struct device, kobj); |
| 457 | struct spi_device *spi = to_spi_device(dev); | 457 | struct spi_device *spi = to_spi_device(dev); |
| 458 | struct tsc2005 *ts = spi_get_drvdata(spi); | 458 | struct tsc2005 *ts = spi_get_drvdata(spi); |
| 459 | umode_t mode = attr->mode; | 459 | mode_t mode = attr->mode; |
| 460 | 460 | ||
| 461 | if (attr == &dev_attr_selftest.attr) { | 461 | if (attr == &dev_attr_selftest.attr) { |
| 462 | if (!ts->set_reset) | 462 | if (!ts->set_reset) |
| @@ -555,7 +555,7 @@ static void tsc2005_close(struct input_dev *input) | |||
| 555 | mutex_unlock(&ts->mutex); | 555 | mutex_unlock(&ts->mutex); |
| 556 | } | 556 | } |
| 557 | 557 | ||
| 558 | static void tsc2005_setup_spi_xfer(struct tsc2005 *ts) | 558 | static void __devinit tsc2005_setup_spi_xfer(struct tsc2005 *ts) |
| 559 | { | 559 | { |
| 560 | tsc2005_setup_read(&ts->spi_x, TSC2005_REG_X, false); | 560 | tsc2005_setup_read(&ts->spi_x, TSC2005_REG_X, false); |
| 561 | tsc2005_setup_read(&ts->spi_y, TSC2005_REG_Y, false); | 561 | tsc2005_setup_read(&ts->spi_y, TSC2005_REG_Y, false); |
| @@ -569,7 +569,7 @@ static void tsc2005_setup_spi_xfer(struct tsc2005 *ts) | |||
| 569 | spi_message_add_tail(&ts->spi_z2.spi_xfer, &ts->spi_read_msg); | 569 | spi_message_add_tail(&ts->spi_z2.spi_xfer, &ts->spi_read_msg); |
| 570 | } | 570 | } |
| 571 | 571 | ||
| 572 | static int tsc2005_probe(struct spi_device *spi) | 572 | static int __devinit tsc2005_probe(struct spi_device *spi) |
| 573 | { | 573 | { |
| 574 | const struct tsc2005_platform_data *pdata = spi->dev.platform_data; | 574 | const struct tsc2005_platform_data *pdata = spi->dev.platform_data; |
| 575 | struct tsc2005 *ts; | 575 | struct tsc2005 *ts; |
| @@ -650,8 +650,7 @@ static int tsc2005_probe(struct spi_device *spi) | |||
| 650 | tsc2005_stop_scan(ts); | 650 | tsc2005_stop_scan(ts); |
| 651 | 651 | ||
| 652 | error = request_threaded_irq(spi->irq, NULL, tsc2005_irq_thread, | 652 | error = request_threaded_irq(spi->irq, NULL, tsc2005_irq_thread, |
| 653 | IRQF_TRIGGER_RISING | IRQF_ONESHOT, | 653 | IRQF_TRIGGER_RISING, "tsc2005", ts); |
| 654 | "tsc2005", ts); | ||
| 655 | if (error) { | 654 | if (error) { |
| 656 | dev_err(&spi->dev, "Failed to request irq, err: %d\n", error); | 655 | dev_err(&spi->dev, "Failed to request irq, err: %d\n", error); |
| 657 | goto err_free_mem; | 656 | goto err_free_mem; |
| @@ -686,7 +685,7 @@ err_free_mem: | |||
| 686 | return error; | 685 | return error; |
| 687 | } | 686 | } |
| 688 | 687 | ||
| 689 | static int tsc2005_remove(struct spi_device *spi) | 688 | static int __devexit tsc2005_remove(struct spi_device *spi) |
| 690 | { | 689 | { |
| 691 | struct tsc2005 *ts = spi_get_drvdata(spi); | 690 | struct tsc2005 *ts = spi_get_drvdata(spi); |
| 692 | 691 | ||
| @@ -745,10 +744,20 @@ static struct spi_driver tsc2005_driver = { | |||
| 745 | .pm = &tsc2005_pm_ops, | 744 | .pm = &tsc2005_pm_ops, |
| 746 | }, | 745 | }, |
| 747 | .probe = tsc2005_probe, | 746 | .probe = tsc2005_probe, |
| 748 | .remove = tsc2005_remove, | 747 | .remove = __devexit_p(tsc2005_remove), |
| 749 | }; | 748 | }; |
| 750 | 749 | ||
| 751 | module_spi_driver(tsc2005_driver); | 750 | static int __init tsc2005_init(void) |
| 751 | { | ||
| 752 | return spi_register_driver(&tsc2005_driver); | ||
| 753 | } | ||
| 754 | module_init(tsc2005_init); | ||
| 755 | |||
| 756 | static void __exit tsc2005_exit(void) | ||
| 757 | { | ||
| 758 | spi_unregister_driver(&tsc2005_driver); | ||
| 759 | } | ||
| 760 | module_exit(tsc2005_exit); | ||
| 752 | 761 | ||
| 753 | MODULE_AUTHOR("Lauri Leukkunen <lauri.leukkunen@nokia.com>"); | 762 | MODULE_AUTHOR("Lauri Leukkunen <lauri.leukkunen@nokia.com>"); |
| 754 | MODULE_DESCRIPTION("TSC2005 Touchscreen Driver"); | 763 | MODULE_DESCRIPTION("TSC2005 Touchscreen Driver"); |
diff --git a/drivers/input/touchscreen/tsc2007.c b/drivers/input/touchscreen/tsc2007.c index 0b67ba476b4..fadc11545b1 100644 --- a/drivers/input/touchscreen/tsc2007.c +++ b/drivers/input/touchscreen/tsc2007.c | |||
| @@ -66,6 +66,7 @@ struct ts_event { | |||
| 66 | struct tsc2007 { | 66 | struct tsc2007 { |
| 67 | struct input_dev *input; | 67 | struct input_dev *input; |
| 68 | char phys[32]; | 68 | char phys[32]; |
| 69 | struct delayed_work work; | ||
| 69 | 70 | ||
| 70 | struct i2c_client *client; | 71 | struct i2c_client *client; |
| 71 | 72 | ||
| @@ -75,11 +76,9 @@ struct tsc2007 { | |||
| 75 | unsigned long poll_delay; | 76 | unsigned long poll_delay; |
| 76 | unsigned long poll_period; | 77 | unsigned long poll_period; |
| 77 | 78 | ||
| 79 | bool pendown; | ||
| 78 | int irq; | 80 | int irq; |
| 79 | 81 | ||
| 80 | wait_queue_head_t wait; | ||
| 81 | bool stopped; | ||
| 82 | |||
| 83 | int (*get_pendown_state)(void); | 82 | int (*get_pendown_state)(void); |
| 84 | void (*clear_penirq)(void); | 83 | void (*clear_penirq)(void); |
| 85 | }; | 84 | }; |
| @@ -142,8 +141,25 @@ static u32 tsc2007_calculate_pressure(struct tsc2007 *tsc, struct ts_event *tc) | |||
| 142 | return rt; | 141 | return rt; |
| 143 | } | 142 | } |
| 144 | 143 | ||
| 145 | static bool tsc2007_is_pen_down(struct tsc2007 *ts) | 144 | static void tsc2007_send_up_event(struct tsc2007 *tsc) |
| 145 | { | ||
| 146 | struct input_dev *input = tsc->input; | ||
| 147 | |||
| 148 | dev_dbg(&tsc->client->dev, "UP\n"); | ||
| 149 | |||
| 150 | input_report_key(input, BTN_TOUCH, 0); | ||
| 151 | input_report_abs(input, ABS_PRESSURE, 0); | ||
| 152 | input_sync(input); | ||
| 153 | } | ||
| 154 | |||
| 155 | static void tsc2007_work(struct work_struct *work) | ||
| 146 | { | 156 | { |
| 157 | struct tsc2007 *ts = | ||
| 158 | container_of(to_delayed_work(work), struct tsc2007, work); | ||
| 159 | bool debounced = false; | ||
| 160 | struct ts_event tc; | ||
| 161 | u32 rt; | ||
| 162 | |||
| 147 | /* | 163 | /* |
| 148 | * NOTE: We can't rely on the pressure to determine the pen down | 164 | * NOTE: We can't rely on the pressure to determine the pen down |
| 149 | * state, even though this controller has a pressure sensor. | 165 | * state, even though this controller has a pressure sensor. |
| @@ -154,82 +170,79 @@ static bool tsc2007_is_pen_down(struct tsc2007 *ts) | |||
| 154 | * The only safe way to check for the pen up condition is in the | 170 | * The only safe way to check for the pen up condition is in the |
| 155 | * work function by reading the pen signal state (it's a GPIO | 171 | * work function by reading the pen signal state (it's a GPIO |
| 156 | * and IRQ). Unfortunately such callback is not always available, | 172 | * and IRQ). Unfortunately such callback is not always available, |
| 157 | * in that case we assume that the pen is down and expect caller | 173 | * in that case we have rely on the pressure anyway. |
| 158 | * to fall back on the pressure reading. | ||
| 159 | */ | 174 | */ |
| 175 | if (ts->get_pendown_state) { | ||
| 176 | if (unlikely(!ts->get_pendown_state())) { | ||
| 177 | tsc2007_send_up_event(ts); | ||
| 178 | ts->pendown = false; | ||
| 179 | goto out; | ||
| 180 | } | ||
| 160 | 181 | ||
| 161 | if (!ts->get_pendown_state) | 182 | dev_dbg(&ts->client->dev, "pen is still down\n"); |
| 162 | return true; | 183 | } |
| 163 | |||
| 164 | return ts->get_pendown_state(); | ||
| 165 | } | ||
| 166 | |||
| 167 | static irqreturn_t tsc2007_soft_irq(int irq, void *handle) | ||
| 168 | { | ||
| 169 | struct tsc2007 *ts = handle; | ||
| 170 | struct input_dev *input = ts->input; | ||
| 171 | struct ts_event tc; | ||
| 172 | u32 rt; | ||
| 173 | 184 | ||
| 174 | while (!ts->stopped && tsc2007_is_pen_down(ts)) { | 185 | tsc2007_read_values(ts, &tc); |
| 175 | 186 | ||
| 176 | /* pen is down, continue with the measurement */ | 187 | rt = tsc2007_calculate_pressure(ts, &tc); |
| 177 | tsc2007_read_values(ts, &tc); | 188 | if (rt > ts->max_rt) { |
| 189 | /* | ||
| 190 | * Sample found inconsistent by debouncing or pressure is | ||
| 191 | * beyond the maximum. Don't report it to user space, | ||
| 192 | * repeat at least once more the measurement. | ||
| 193 | */ | ||
| 194 | dev_dbg(&ts->client->dev, "ignored pressure %d\n", rt); | ||
| 195 | debounced = true; | ||
| 196 | goto out; | ||
| 178 | 197 | ||
| 179 | rt = tsc2007_calculate_pressure(ts, &tc); | 198 | } |
| 180 | 199 | ||
| 181 | if (rt == 0 && !ts->get_pendown_state) { | 200 | if (rt) { |
| 182 | /* | 201 | struct input_dev *input = ts->input; |
| 183 | * If pressure reported is 0 and we don't have | ||
| 184 | * callback to check pendown state, we have to | ||
| 185 | * assume that pen was lifted up. | ||
| 186 | */ | ||
| 187 | break; | ||
| 188 | } | ||
| 189 | 202 | ||
| 190 | if (rt <= ts->max_rt) { | 203 | if (!ts->pendown) { |
| 191 | dev_dbg(&ts->client->dev, | 204 | dev_dbg(&ts->client->dev, "DOWN\n"); |
| 192 | "DOWN point(%4d,%4d), pressure (%4u)\n", | ||
| 193 | tc.x, tc.y, rt); | ||
| 194 | 205 | ||
| 195 | input_report_key(input, BTN_TOUCH, 1); | 206 | input_report_key(input, BTN_TOUCH, 1); |
| 196 | input_report_abs(input, ABS_X, tc.x); | 207 | ts->pendown = true; |
| 197 | input_report_abs(input, ABS_Y, tc.y); | ||
| 198 | input_report_abs(input, ABS_PRESSURE, rt); | ||
| 199 | |||
| 200 | input_sync(input); | ||
| 201 | |||
| 202 | } else { | ||
| 203 | /* | ||
| 204 | * Sample found inconsistent by debouncing or pressure is | ||
| 205 | * beyond the maximum. Don't report it to user space, | ||
| 206 | * repeat at least once more the measurement. | ||
| 207 | */ | ||
| 208 | dev_dbg(&ts->client->dev, "ignored pressure %d\n", rt); | ||
| 209 | } | 208 | } |
| 210 | 209 | ||
| 211 | wait_event_timeout(ts->wait, ts->stopped, | 210 | input_report_abs(input, ABS_X, tc.x); |
| 212 | msecs_to_jiffies(ts->poll_period)); | 211 | input_report_abs(input, ABS_Y, tc.y); |
| 213 | } | 212 | input_report_abs(input, ABS_PRESSURE, rt); |
| 214 | 213 | ||
| 215 | dev_dbg(&ts->client->dev, "UP\n"); | 214 | input_sync(input); |
| 216 | 215 | ||
| 217 | input_report_key(input, BTN_TOUCH, 0); | 216 | dev_dbg(&ts->client->dev, "point(%4d,%4d), pressure (%4u)\n", |
| 218 | input_report_abs(input, ABS_PRESSURE, 0); | 217 | tc.x, tc.y, rt); |
| 219 | input_sync(input); | ||
| 220 | 218 | ||
| 221 | if (ts->clear_penirq) | 219 | } else if (!ts->get_pendown_state && ts->pendown) { |
| 222 | ts->clear_penirq(); | 220 | /* |
| 221 | * We don't have callback to check pendown state, so we | ||
| 222 | * have to assume that since pressure reported is 0 the | ||
| 223 | * pen was lifted up. | ||
| 224 | */ | ||
| 225 | tsc2007_send_up_event(ts); | ||
| 226 | ts->pendown = false; | ||
| 227 | } | ||
| 223 | 228 | ||
| 224 | return IRQ_HANDLED; | 229 | out: |
| 230 | if (ts->pendown || debounced) | ||
| 231 | schedule_delayed_work(&ts->work, | ||
| 232 | msecs_to_jiffies(ts->poll_period)); | ||
| 233 | else | ||
| 234 | enable_irq(ts->irq); | ||
| 225 | } | 235 | } |
| 226 | 236 | ||
| 227 | static irqreturn_t tsc2007_hard_irq(int irq, void *handle) | 237 | static irqreturn_t tsc2007_irq(int irq, void *handle) |
| 228 | { | 238 | { |
| 229 | struct tsc2007 *ts = handle; | 239 | struct tsc2007 *ts = handle; |
| 230 | 240 | ||
| 231 | if (!ts->get_pendown_state || likely(ts->get_pendown_state())) | 241 | if (!ts->get_pendown_state || likely(ts->get_pendown_state())) { |
| 232 | return IRQ_WAKE_THREAD; | 242 | disable_irq_nosync(ts->irq); |
| 243 | schedule_delayed_work(&ts->work, | ||
| 244 | msecs_to_jiffies(ts->poll_delay)); | ||
| 245 | } | ||
| 233 | 246 | ||
| 234 | if (ts->clear_penirq) | 247 | if (ts->clear_penirq) |
| 235 | ts->clear_penirq(); | 248 | ts->clear_penirq(); |
| @@ -237,43 +250,20 @@ static irqreturn_t tsc2007_hard_irq(int irq, void *handle) | |||
| 237 | return IRQ_HANDLED; | 250 | return IRQ_HANDLED; |
| 238 | } | 251 | } |
| 239 | 252 | ||
| 240 | static void tsc2007_stop(struct tsc2007 *ts) | 253 | static void tsc2007_free_irq(struct tsc2007 *ts) |
| 241 | { | ||
| 242 | ts->stopped = true; | ||
| 243 | mb(); | ||
| 244 | wake_up(&ts->wait); | ||
| 245 | |||
| 246 | disable_irq(ts->irq); | ||
| 247 | } | ||
| 248 | |||
| 249 | static int tsc2007_open(struct input_dev *input_dev) | ||
| 250 | { | 254 | { |
| 251 | struct tsc2007 *ts = input_get_drvdata(input_dev); | 255 | free_irq(ts->irq, ts); |
| 252 | int err; | 256 | if (cancel_delayed_work_sync(&ts->work)) { |
| 253 | 257 | /* | |
| 254 | ts->stopped = false; | 258 | * Work was pending, therefore we need to enable |
| 255 | mb(); | 259 | * IRQ here to balance the disable_irq() done in the |
| 256 | 260 | * interrupt handler. | |
| 257 | enable_irq(ts->irq); | 261 | */ |
| 258 | 262 | enable_irq(ts->irq); | |
| 259 | /* Prepare for touch readings - power down ADC and enable PENIRQ */ | ||
| 260 | err = tsc2007_xfer(ts, PWRDOWN); | ||
| 261 | if (err < 0) { | ||
| 262 | tsc2007_stop(ts); | ||
| 263 | return err; | ||
| 264 | } | 263 | } |
| 265 | |||
| 266 | return 0; | ||
| 267 | } | ||
| 268 | |||
| 269 | static void tsc2007_close(struct input_dev *input_dev) | ||
| 270 | { | ||
| 271 | struct tsc2007 *ts = input_get_drvdata(input_dev); | ||
| 272 | |||
| 273 | tsc2007_stop(ts); | ||
| 274 | } | 264 | } |
| 275 | 265 | ||
| 276 | static int tsc2007_probe(struct i2c_client *client, | 266 | static int __devinit tsc2007_probe(struct i2c_client *client, |
| 277 | const struct i2c_device_id *id) | 267 | const struct i2c_device_id *id) |
| 278 | { | 268 | { |
| 279 | struct tsc2007 *ts; | 269 | struct tsc2007 *ts; |
| @@ -300,7 +290,7 @@ static int tsc2007_probe(struct i2c_client *client, | |||
| 300 | ts->client = client; | 290 | ts->client = client; |
| 301 | ts->irq = client->irq; | 291 | ts->irq = client->irq; |
| 302 | ts->input = input_dev; | 292 | ts->input = input_dev; |
| 303 | init_waitqueue_head(&ts->wait); | 293 | INIT_DELAYED_WORK(&ts->work, tsc2007_work); |
| 304 | 294 | ||
| 305 | ts->model = pdata->model; | 295 | ts->model = pdata->model; |
| 306 | ts->x_plate_ohms = pdata->x_plate_ohms; | 296 | ts->x_plate_ohms = pdata->x_plate_ohms; |
| @@ -310,12 +300,6 @@ static int tsc2007_probe(struct i2c_client *client, | |||
| 310 | ts->get_pendown_state = pdata->get_pendown_state; | 300 | ts->get_pendown_state = pdata->get_pendown_state; |
| 311 | ts->clear_penirq = pdata->clear_penirq; | 301 | ts->clear_penirq = pdata->clear_penirq; |
| 312 | 302 | ||
| 313 | if (pdata->x_plate_ohms == 0) { | ||
| 314 | dev_err(&client->dev, "x_plate_ohms is not set up in platform data"); | ||
| 315 | err = -EINVAL; | ||
| 316 | goto err_free_mem; | ||
| 317 | } | ||
| 318 | |||
| 319 | snprintf(ts->phys, sizeof(ts->phys), | 303 | snprintf(ts->phys, sizeof(ts->phys), |
| 320 | "%s/input0", dev_name(&client->dev)); | 304 | "%s/input0", dev_name(&client->dev)); |
| 321 | 305 | ||
| @@ -323,11 +307,6 @@ static int tsc2007_probe(struct i2c_client *client, | |||
| 323 | input_dev->phys = ts->phys; | 307 | input_dev->phys = ts->phys; |
| 324 | input_dev->id.bustype = BUS_I2C; | 308 | input_dev->id.bustype = BUS_I2C; |
| 325 | 309 | ||
| 326 | input_dev->open = tsc2007_open; | ||
| 327 | input_dev->close = tsc2007_close; | ||
| 328 | |||
| 329 | input_set_drvdata(input_dev, ts); | ||
| 330 | |||
| 331 | input_dev->evbit[0] = BIT_MASK(EV_KEY) | BIT_MASK(EV_ABS); | 310 | input_dev->evbit[0] = BIT_MASK(EV_KEY) | BIT_MASK(EV_ABS); |
| 332 | input_dev->keybit[BIT_WORD(BTN_TOUCH)] = BIT_MASK(BTN_TOUCH); | 311 | input_dev->keybit[BIT_WORD(BTN_TOUCH)] = BIT_MASK(BTN_TOUCH); |
| 333 | 312 | ||
| @@ -339,14 +318,17 @@ static int tsc2007_probe(struct i2c_client *client, | |||
| 339 | if (pdata->init_platform_hw) | 318 | if (pdata->init_platform_hw) |
| 340 | pdata->init_platform_hw(); | 319 | pdata->init_platform_hw(); |
| 341 | 320 | ||
| 342 | err = request_threaded_irq(ts->irq, tsc2007_hard_irq, tsc2007_soft_irq, | 321 | err = request_irq(ts->irq, tsc2007_irq, 0, |
| 343 | IRQF_ONESHOT, client->dev.driver->name, ts); | 322 | client->dev.driver->name, ts); |
| 344 | if (err < 0) { | 323 | if (err < 0) { |
| 345 | dev_err(&client->dev, "irq %d busy?\n", ts->irq); | 324 | dev_err(&client->dev, "irq %d busy?\n", ts->irq); |
| 346 | goto err_free_mem; | 325 | goto err_free_mem; |
| 347 | } | 326 | } |
| 348 | 327 | ||
| 349 | tsc2007_stop(ts); | 328 | /* Prepare for touch readings - power down ADC and enable PENIRQ */ |
| 329 | err = tsc2007_xfer(ts, PWRDOWN); | ||
| 330 | if (err < 0) | ||
| 331 | goto err_free_irq; | ||
| 350 | 332 | ||
| 351 | err = input_register_device(input_dev); | 333 | err = input_register_device(input_dev); |
| 352 | if (err) | 334 | if (err) |
| @@ -357,7 +339,7 @@ static int tsc2007_probe(struct i2c_client *client, | |||
| 357 | return 0; | 339 | return 0; |
| 358 | 340 | ||
| 359 | err_free_irq: | 341 | err_free_irq: |
| 360 | free_irq(ts->irq, ts); | 342 | tsc2007_free_irq(ts); |
| 361 | if (pdata->exit_platform_hw) | 343 | if (pdata->exit_platform_hw) |
| 362 | pdata->exit_platform_hw(); | 344 | pdata->exit_platform_hw(); |
| 363 | err_free_mem: | 345 | err_free_mem: |
| @@ -366,12 +348,12 @@ static int tsc2007_probe(struct i2c_client *client, | |||
| 366 | return err; | 348 | return err; |
| 367 | } | 349 | } |
| 368 | 350 | ||
| 369 | static int tsc2007_remove(struct i2c_client *client) | 351 | static int __devexit tsc2007_remove(struct i2c_client *client) |
| 370 | { | 352 | { |
| 371 | struct tsc2007 *ts = i2c_get_clientdata(client); | 353 | struct tsc2007 *ts = i2c_get_clientdata(client); |
| 372 | struct tsc2007_platform_data *pdata = client->dev.platform_data; | 354 | struct tsc2007_platform_data *pdata = client->dev.platform_data; |
| 373 | 355 | ||
| 374 | free_irq(ts->irq, ts); | 356 | tsc2007_free_irq(ts); |
| 375 | 357 | ||
| 376 | if (pdata->exit_platform_hw) | 358 | if (pdata->exit_platform_hw) |
| 377 | pdata->exit_platform_hw(); | 359 | pdata->exit_platform_hw(); |
| @@ -396,10 +378,21 @@ static struct i2c_driver tsc2007_driver = { | |||
| 396 | }, | 378 | }, |
| 397 | .id_table = tsc2007_idtable, | 379 | .id_table = tsc2007_idtable, |
| 398 | .probe = tsc2007_probe, | 380 | .probe = tsc2007_probe, |
| 399 | .remove = tsc2007_remove, | 381 | .remove = __devexit_p(tsc2007_remove), |
| 400 | }; | 382 | }; |
| 401 | 383 | ||
| 402 | module_i2c_driver(tsc2007_driver); | 384 | static int __init tsc2007_init(void) |
| 385 | { | ||
| 386 | return i2c_add_driver(&tsc2007_driver); | ||
| 387 | } | ||
| 388 | |||
| 389 | static void __exit tsc2007_exit(void) | ||
| 390 | { | ||
| 391 | i2c_del_driver(&tsc2007_driver); | ||
| 392 | } | ||
| 393 | |||
| 394 | module_init(tsc2007_init); | ||
| 395 | module_exit(tsc2007_exit); | ||
| 403 | 396 | ||
| 404 | MODULE_AUTHOR("Kwangwoo Lee <kwlee@mtekvision.com>"); | 397 | MODULE_AUTHOR("Kwangwoo Lee <kwlee@mtekvision.com>"); |
| 405 | MODULE_DESCRIPTION("TSC2007 TouchScreen Driver"); | 398 | MODULE_DESCRIPTION("TSC2007 TouchScreen Driver"); |
diff --git a/drivers/input/touchscreen/tsc40.c b/drivers/input/touchscreen/tsc40.c deleted file mode 100644 index eb96f168fb9..00000000000 --- a/drivers/input/touchscreen/tsc40.c +++ /dev/null | |||
| @@ -1,173 +0,0 @@ | |||
| 1 | /* | ||
| 2 | * TSC-40 serial touchscreen driver. It should be compatible with | ||
| 3 | * TSC-10 and 25. | ||
| 4 | * | ||
| 5 | * Author: Sebastian Andrzej Siewior <bigeasy@linutronix.de> | ||
| 6 | * License: GPLv2 as published by the FSF. | ||
| 7 | */ | ||
| 8 | |||
| 9 | #include <linux/kernel.h> | ||
| 10 | #include <linux/module.h> | ||
| 11 | #include <linux/slab.h> | ||
| 12 | #include <linux/input.h> | ||
| 13 | #include <linux/serio.h> | ||
| 14 | #include <linux/init.h> | ||
| 15 | |||
| 16 | #define PACKET_LENGTH 5 | ||
| 17 | struct tsc_ser { | ||
| 18 | struct input_dev *dev; | ||
| 19 | struct serio *serio; | ||
| 20 | u32 idx; | ||
| 21 | unsigned char data[PACKET_LENGTH]; | ||
| 22 | char phys[32]; | ||
| 23 | }; | ||
| 24 | |||
| 25 | static void tsc_process_data(struct tsc_ser *ptsc) | ||
| 26 | { | ||
| 27 | struct input_dev *dev = ptsc->dev; | ||
| 28 | u8 *data = ptsc->data; | ||
| 29 | u32 x; | ||
| 30 | u32 y; | ||
| 31 | |||
| 32 | x = ((data[1] & 0x03) << 8) | data[2]; | ||
| 33 | y = ((data[3] & 0x03) << 8) | data[4]; | ||
| 34 | |||
| 35 | input_report_abs(dev, ABS_X, x); | ||
| 36 | input_report_abs(dev, ABS_Y, y); | ||
| 37 | input_report_key(dev, BTN_TOUCH, 1); | ||
| 38 | |||
| 39 | input_sync(dev); | ||
| 40 | } | ||
| 41 | |||
| 42 | static irqreturn_t tsc_interrupt(struct serio *serio, | ||
| 43 | unsigned char data, unsigned int flags) | ||
| 44 | { | ||
| 45 | struct tsc_ser *ptsc = serio_get_drvdata(serio); | ||
| 46 | struct input_dev *dev = ptsc->dev; | ||
| 47 | |||
| 48 | ptsc->data[ptsc->idx] = data; | ||
| 49 | switch (ptsc->idx++) { | ||
| 50 | case 0: | ||
| 51 | if (unlikely((data & 0x3e) != 0x10)) { | ||
| 52 | dev_dbg(&serio->dev, | ||
| 53 | "unsynchronized packet start (0x%02x)\n", data); | ||
| 54 | ptsc->idx = 0; | ||
| 55 | } else if (!(data & 0x01)) { | ||
| 56 | input_report_key(dev, BTN_TOUCH, 0); | ||
| 57 | input_sync(dev); | ||
| 58 | ptsc->idx = 0; | ||
| 59 | } | ||
| 60 | break; | ||
| 61 | |||
| 62 | case 1: | ||
| 63 | case 3: | ||
| 64 | if (unlikely(data & 0xfc)) { | ||
| 65 | dev_dbg(&serio->dev, | ||
| 66 | "unsynchronized data 0x%02x at offset %d\n", | ||
| 67 | data, ptsc->idx - 1); | ||
| 68 | ptsc->idx = 0; | ||
| 69 | } | ||
| 70 | break; | ||
| 71 | |||
| 72 | case 4: | ||
| 73 | tsc_process_data(ptsc); | ||
| 74 | ptsc->idx = 0; | ||
| 75 | break; | ||
| 76 | } | ||
| 77 | |||
| 78 | return IRQ_HANDLED; | ||
| 79 | } | ||
| 80 | |||
| 81 | static int tsc_connect(struct serio *serio, struct serio_driver *drv) | ||
| 82 | { | ||
| 83 | struct tsc_ser *ptsc; | ||
| 84 | struct input_dev *input_dev; | ||
| 85 | int error; | ||
| 86 | |||
| 87 | ptsc = kzalloc(sizeof(struct tsc_ser), GFP_KERNEL); | ||
| 88 | input_dev = input_allocate_device(); | ||
| 89 | if (!ptsc || !input_dev) { | ||
| 90 | error = -ENOMEM; | ||
| 91 | goto fail1; | ||
| 92 | } | ||
| 93 | |||
| 94 | ptsc->serio = serio; | ||
| 95 | ptsc->dev = input_dev; | ||
| 96 | snprintf(ptsc->phys, sizeof(ptsc->phys), "%s/input0", serio->phys); | ||
| 97 | |||
| 98 | input_dev->name = "TSC-10/25/40 Serial TouchScreen"; | ||
| 99 | input_dev->phys = ptsc->phys; | ||
| 100 | input_dev->id.bustype = BUS_RS232; | ||
| 101 | input_dev->id.vendor = SERIO_TSC40; | ||
| 102 | input_dev->id.product = 40; | ||
| 103 | input_dev->id.version = 0x0001; | ||
| 104 | input_dev->dev.parent = &serio->dev; | ||
| 105 | |||
| 106 | input_dev->evbit[0] = BIT_MASK(EV_KEY) | BIT_MASK(EV_ABS); | ||
| 107 | __set_bit(BTN_TOUCH, input_dev->keybit); | ||
| 108 | input_set_abs_params(ptsc->dev, ABS_X, 0, 0x3ff, 0, 0); | ||
| 109 | input_set_abs_params(ptsc->dev, ABS_Y, 0, 0x3ff, 0, 0); | ||
| 110 | |||
| 111 | serio_set_drvdata(serio, ptsc); | ||
| 112 | |||
| 113 | error = serio_open(serio, drv); | ||
| 114 | if (error) | ||
| 115 | goto fail2; | ||
| 116 | |||
| 117 | error = input_register_device(ptsc->dev); | ||
| 118 | if (error) | ||
| 119 | goto fail3; | ||
| 120 | |||
| 121 | return 0; | ||
| 122 | |||
| 123 | fail3: | ||
| 124 | serio_close(serio); | ||
| 125 | fail2: | ||
| 126 | serio_set_drvdata(serio, NULL); | ||
| 127 | fail1: | ||
| 128 | input_free_device(input_dev); | ||
| 129 | kfree(ptsc); | ||
| 130 | return error; | ||
| 131 | } | ||
| 132 | |||
| 133 | static void tsc_disconnect(struct serio *serio) | ||
| 134 | { | ||
| 135 | struct tsc_ser *ptsc = serio_get_drvdata(serio); | ||
| 136 | |||
| 137 | serio_close(serio); | ||
| 138 | |||
| 139 | input_unregister_device(ptsc->dev); | ||
| 140 | kfree(ptsc); | ||
| 141 | |||
| 142 | serio_set_drvdata(serio, NULL); | ||
| 143 | } | ||
| 144 | |||
| 145 | static struct serio_device_id tsc_serio_ids[] = { | ||
| 146 | { | ||
| 147 | .type = SERIO_RS232, | ||
| 148 | .proto = SERIO_TSC40, | ||
| 149 | .id = SERIO_ANY, | ||
| 150 | .extra = SERIO_ANY, | ||
| 151 | }, | ||
| 152 | { 0 } | ||
| 153 | }; | ||
| 154 | MODULE_DEVICE_TABLE(serio, tsc_serio_ids); | ||
| 155 | |||
| 156 | #define DRIVER_DESC "TSC-10/25/40 serial touchscreen driver" | ||
| 157 | |||
| 158 | static struct serio_driver tsc_drv = { | ||
| 159 | .driver = { | ||
| 160 | .name = "tsc40", | ||
| 161 | }, | ||
| 162 | .description = DRIVER_DESC, | ||
| 163 | .id_table = tsc_serio_ids, | ||
| 164 | .interrupt = tsc_interrupt, | ||
| 165 | .connect = tsc_connect, | ||
| 166 | .disconnect = tsc_disconnect, | ||
| 167 | }; | ||
| 168 | |||
| 169 | module_serio_driver(tsc_drv); | ||
| 170 | |||
| 171 | MODULE_AUTHOR("Sebastian Andrzej Siewior <bigeasy@linutronix.de>"); | ||
| 172 | MODULE_DESCRIPTION(DRIVER_DESC); | ||
| 173 | MODULE_LICENSE("GPL v2"); | ||
diff --git a/drivers/input/touchscreen/ucb1400_ts.c b/drivers/input/touchscreen/ucb1400_ts.c index 1271f97b407..3b5b5df04dd 100644 --- a/drivers/input/touchscreen/ucb1400_ts.c +++ b/drivers/input/touchscreen/ucb1400_ts.c | |||
| @@ -20,24 +20,24 @@ | |||
| 20 | 20 | ||
| 21 | #include <linux/module.h> | 21 | #include <linux/module.h> |
| 22 | #include <linux/init.h> | 22 | #include <linux/init.h> |
| 23 | #include <linux/completion.h> | ||
| 23 | #include <linux/delay.h> | 24 | #include <linux/delay.h> |
| 24 | #include <linux/sched.h> | ||
| 25 | #include <linux/wait.h> | ||
| 26 | #include <linux/input.h> | 25 | #include <linux/input.h> |
| 27 | #include <linux/device.h> | 26 | #include <linux/device.h> |
| 28 | #include <linux/interrupt.h> | 27 | #include <linux/interrupt.h> |
| 28 | #include <linux/suspend.h> | ||
| 29 | #include <linux/kthread.h> | ||
| 30 | #include <linux/freezer.h> | ||
| 29 | #include <linux/ucb1400.h> | 31 | #include <linux/ucb1400.h> |
| 30 | 32 | ||
| 31 | #define UCB1400_TS_POLL_PERIOD 10 /* ms */ | 33 | static int adcsync; |
| 32 | |||
| 33 | static bool adcsync; | ||
| 34 | static int ts_delay = 55; /* us */ | 34 | static int ts_delay = 55; /* us */ |
| 35 | static int ts_delay_pressure; /* us */ | 35 | static int ts_delay_pressure; /* us */ |
| 36 | 36 | ||
| 37 | /* Switch to interrupt mode. */ | 37 | /* Switch to interrupt mode. */ |
| 38 | static void ucb1400_ts_mode_int(struct ucb1400_ts *ucb) | 38 | static inline void ucb1400_ts_mode_int(struct snd_ac97 *ac97) |
| 39 | { | 39 | { |
| 40 | ucb1400_reg_write(ucb->ac97, UCB_TS_CR, | 40 | ucb1400_reg_write(ac97, UCB_TS_CR, |
| 41 | UCB_TS_CR_TSMX_POW | UCB_TS_CR_TSPX_POW | | 41 | UCB_TS_CR_TSMX_POW | UCB_TS_CR_TSPX_POW | |
| 42 | UCB_TS_CR_TSMY_GND | UCB_TS_CR_TSPY_GND | | 42 | UCB_TS_CR_TSMY_GND | UCB_TS_CR_TSPY_GND | |
| 43 | UCB_TS_CR_MODE_INT); | 43 | UCB_TS_CR_MODE_INT); |
| @@ -47,15 +47,13 @@ static void ucb1400_ts_mode_int(struct ucb1400_ts *ucb) | |||
| 47 | * Switch to pressure mode, and read pressure. We don't need to wait | 47 | * Switch to pressure mode, and read pressure. We don't need to wait |
| 48 | * here, since both plates are being driven. | 48 | * here, since both plates are being driven. |
| 49 | */ | 49 | */ |
| 50 | static unsigned int ucb1400_ts_read_pressure(struct ucb1400_ts *ucb) | 50 | static inline unsigned int ucb1400_ts_read_pressure(struct ucb1400_ts *ucb) |
| 51 | { | 51 | { |
| 52 | ucb1400_reg_write(ucb->ac97, UCB_TS_CR, | 52 | ucb1400_reg_write(ucb->ac97, UCB_TS_CR, |
| 53 | UCB_TS_CR_TSMX_POW | UCB_TS_CR_TSPX_POW | | 53 | UCB_TS_CR_TSMX_POW | UCB_TS_CR_TSPX_POW | |
| 54 | UCB_TS_CR_TSMY_GND | UCB_TS_CR_TSPY_GND | | 54 | UCB_TS_CR_TSMY_GND | UCB_TS_CR_TSPY_GND | |
| 55 | UCB_TS_CR_MODE_PRES | UCB_TS_CR_BIAS_ENA); | 55 | UCB_TS_CR_MODE_PRES | UCB_TS_CR_BIAS_ENA); |
| 56 | |||
| 57 | udelay(ts_delay_pressure); | 56 | udelay(ts_delay_pressure); |
| 58 | |||
| 59 | return ucb1400_adc_read(ucb->ac97, UCB_ADC_INP_TSPY, adcsync); | 57 | return ucb1400_adc_read(ucb->ac97, UCB_ADC_INP_TSPY, adcsync); |
| 60 | } | 58 | } |
| 61 | 59 | ||
| @@ -65,7 +63,7 @@ static unsigned int ucb1400_ts_read_pressure(struct ucb1400_ts *ucb) | |||
| 65 | * gives a faster response time. Even so, we need to wait about 55us | 63 | * gives a faster response time. Even so, we need to wait about 55us |
| 66 | * for things to stabilise. | 64 | * for things to stabilise. |
| 67 | */ | 65 | */ |
| 68 | static unsigned int ucb1400_ts_read_xpos(struct ucb1400_ts *ucb) | 66 | static inline unsigned int ucb1400_ts_read_xpos(struct ucb1400_ts *ucb) |
| 69 | { | 67 | { |
| 70 | ucb1400_reg_write(ucb->ac97, UCB_TS_CR, | 68 | ucb1400_reg_write(ucb->ac97, UCB_TS_CR, |
| 71 | UCB_TS_CR_TSMX_GND | UCB_TS_CR_TSPX_POW | | 69 | UCB_TS_CR_TSMX_GND | UCB_TS_CR_TSPX_POW | |
| @@ -88,7 +86,7 @@ static unsigned int ucb1400_ts_read_xpos(struct ucb1400_ts *ucb) | |||
| 88 | * gives a faster response time. Even so, we need to wait about 55us | 86 | * gives a faster response time. Even so, we need to wait about 55us |
| 89 | * for things to stabilise. | 87 | * for things to stabilise. |
| 90 | */ | 88 | */ |
| 91 | static int ucb1400_ts_read_ypos(struct ucb1400_ts *ucb) | 89 | static inline unsigned int ucb1400_ts_read_ypos(struct ucb1400_ts *ucb) |
| 92 | { | 90 | { |
| 93 | ucb1400_reg_write(ucb->ac97, UCB_TS_CR, | 91 | ucb1400_reg_write(ucb->ac97, UCB_TS_CR, |
| 94 | UCB_TS_CR_TSMY_GND | UCB_TS_CR_TSPY_POW | | 92 | UCB_TS_CR_TSMY_GND | UCB_TS_CR_TSPY_POW | |
| @@ -109,7 +107,7 @@ static int ucb1400_ts_read_ypos(struct ucb1400_ts *ucb) | |||
| 109 | * Switch to X plate resistance mode. Set MX to ground, PX to | 107 | * Switch to X plate resistance mode. Set MX to ground, PX to |
| 110 | * supply. Measure current. | 108 | * supply. Measure current. |
| 111 | */ | 109 | */ |
| 112 | static unsigned int ucb1400_ts_read_xres(struct ucb1400_ts *ucb) | 110 | static inline unsigned int ucb1400_ts_read_xres(struct ucb1400_ts *ucb) |
| 113 | { | 111 | { |
| 114 | ucb1400_reg_write(ucb->ac97, UCB_TS_CR, | 112 | ucb1400_reg_write(ucb->ac97, UCB_TS_CR, |
| 115 | UCB_TS_CR_TSMX_GND | UCB_TS_CR_TSPX_POW | | 113 | UCB_TS_CR_TSMX_GND | UCB_TS_CR_TSPX_POW | |
| @@ -121,7 +119,7 @@ static unsigned int ucb1400_ts_read_xres(struct ucb1400_ts *ucb) | |||
| 121 | * Switch to Y plate resistance mode. Set MY to ground, PY to | 119 | * Switch to Y plate resistance mode. Set MY to ground, PY to |
| 122 | * supply. Measure current. | 120 | * supply. Measure current. |
| 123 | */ | 121 | */ |
| 124 | static unsigned int ucb1400_ts_read_yres(struct ucb1400_ts *ucb) | 122 | static inline unsigned int ucb1400_ts_read_yres(struct ucb1400_ts *ucb) |
| 125 | { | 123 | { |
| 126 | ucb1400_reg_write(ucb->ac97, UCB_TS_CR, | 124 | ucb1400_reg_write(ucb->ac97, UCB_TS_CR, |
| 127 | UCB_TS_CR_TSMY_GND | UCB_TS_CR_TSPY_POW | | 125 | UCB_TS_CR_TSMY_GND | UCB_TS_CR_TSPY_POW | |
| @@ -129,26 +127,26 @@ static unsigned int ucb1400_ts_read_yres(struct ucb1400_ts *ucb) | |||
| 129 | return ucb1400_adc_read(ucb->ac97, 0, adcsync); | 127 | return ucb1400_adc_read(ucb->ac97, 0, adcsync); |
| 130 | } | 128 | } |
| 131 | 129 | ||
| 132 | static int ucb1400_ts_pen_up(struct ucb1400_ts *ucb) | 130 | static inline int ucb1400_ts_pen_up(struct snd_ac97 *ac97) |
| 133 | { | 131 | { |
| 134 | unsigned short val = ucb1400_reg_read(ucb->ac97, UCB_TS_CR); | 132 | unsigned short val = ucb1400_reg_read(ac97, UCB_TS_CR); |
| 135 | 133 | ||
| 136 | return val & (UCB_TS_CR_TSPX_LOW | UCB_TS_CR_TSMX_LOW); | 134 | return val & (UCB_TS_CR_TSPX_LOW | UCB_TS_CR_TSMX_LOW); |
| 137 | } | 135 | } |
| 138 | 136 | ||
| 139 | static void ucb1400_ts_irq_enable(struct ucb1400_ts *ucb) | 137 | static inline void ucb1400_ts_irq_enable(struct snd_ac97 *ac97) |
| 140 | { | 138 | { |
| 141 | ucb1400_reg_write(ucb->ac97, UCB_IE_CLEAR, UCB_IE_TSPX); | 139 | ucb1400_reg_write(ac97, UCB_IE_CLEAR, UCB_IE_TSPX); |
| 142 | ucb1400_reg_write(ucb->ac97, UCB_IE_CLEAR, 0); | 140 | ucb1400_reg_write(ac97, UCB_IE_CLEAR, 0); |
| 143 | ucb1400_reg_write(ucb->ac97, UCB_IE_FAL, UCB_IE_TSPX); | 141 | ucb1400_reg_write(ac97, UCB_IE_FAL, UCB_IE_TSPX); |
| 144 | } | 142 | } |
| 145 | 143 | ||
| 146 | static void ucb1400_ts_irq_disable(struct ucb1400_ts *ucb) | 144 | static inline void ucb1400_ts_irq_disable(struct snd_ac97 *ac97) |
| 147 | { | 145 | { |
| 148 | ucb1400_reg_write(ucb->ac97, UCB_IE_FAL, 0); | 146 | ucb1400_reg_write(ac97, UCB_IE_FAL, 0); |
| 149 | } | 147 | } |
| 150 | 148 | ||
| 151 | static void ucb1400_ts_report_event(struct input_dev *idev, u16 pressure, u16 x, u16 y) | 149 | static void ucb1400_ts_evt_add(struct input_dev *idev, u16 pressure, u16 x, u16 y) |
| 152 | { | 150 | { |
| 153 | input_report_abs(idev, ABS_X, x); | 151 | input_report_abs(idev, ABS_X, x); |
| 154 | input_report_abs(idev, ABS_Y, y); | 152 | input_report_abs(idev, ABS_Y, y); |
| @@ -164,7 +162,7 @@ static void ucb1400_ts_event_release(struct input_dev *idev) | |||
| 164 | input_sync(idev); | 162 | input_sync(idev); |
| 165 | } | 163 | } |
| 166 | 164 | ||
| 167 | static void ucb1400_clear_pending_irq(struct ucb1400_ts *ucb) | 165 | static void ucb1400_handle_pending_irq(struct ucb1400_ts *ucb) |
| 168 | { | 166 | { |
| 169 | unsigned int isr; | 167 | unsigned int isr; |
| 170 | 168 | ||
| @@ -173,34 +171,32 @@ static void ucb1400_clear_pending_irq(struct ucb1400_ts *ucb) | |||
| 173 | ucb1400_reg_write(ucb->ac97, UCB_IE_CLEAR, 0); | 171 | ucb1400_reg_write(ucb->ac97, UCB_IE_CLEAR, 0); |
| 174 | 172 | ||
| 175 | if (isr & UCB_IE_TSPX) | 173 | if (isr & UCB_IE_TSPX) |
| 176 | ucb1400_ts_irq_disable(ucb); | 174 | ucb1400_ts_irq_disable(ucb->ac97); |
| 177 | else | 175 | else |
| 178 | dev_dbg(&ucb->ts_idev->dev, | 176 | dev_dbg(&ucb->ts_idev->dev, "ucb1400: unexpected IE_STATUS = %#x\n", isr); |
| 179 | "ucb1400: unexpected IE_STATUS = %#x\n", isr); | 177 | enable_irq(ucb->irq); |
| 180 | } | 178 | } |
| 181 | 179 | ||
| 182 | /* | 180 | static int ucb1400_ts_thread(void *_ucb) |
| 183 | * A restriction with interrupts exists when using the ucb1400, as | ||
| 184 | * the codec read/write routines may sleep while waiting for codec | ||
| 185 | * access completion and uses semaphores for access control to the | ||
| 186 | * AC97 bus. Therefore the driver is forced to use threaded interrupt | ||
| 187 | * handler. | ||
| 188 | */ | ||
| 189 | static irqreturn_t ucb1400_irq(int irqnr, void *devid) | ||
| 190 | { | 181 | { |
| 191 | struct ucb1400_ts *ucb = devid; | 182 | struct ucb1400_ts *ucb = _ucb; |
| 192 | unsigned int x, y, p; | 183 | struct task_struct *tsk = current; |
| 193 | bool penup; | 184 | int valid = 0; |
| 185 | struct sched_param param = { .sched_priority = 1 }; | ||
| 194 | 186 | ||
| 195 | if (unlikely(irqnr != ucb->irq)) | 187 | sched_setscheduler(tsk, SCHED_FIFO, ¶m); |
| 196 | return IRQ_NONE; | ||
| 197 | 188 | ||
| 198 | ucb1400_clear_pending_irq(ucb); | 189 | set_freezable(); |
| 190 | while (!kthread_should_stop()) { | ||
| 191 | unsigned int x, y, p; | ||
| 192 | long timeout; | ||
| 199 | 193 | ||
| 200 | /* Start with a small delay before checking pendown state */ | 194 | ucb->ts_restart = 0; |
| 201 | msleep(UCB1400_TS_POLL_PERIOD); | ||
| 202 | 195 | ||
| 203 | while (!ucb->stopped && !(penup = ucb1400_ts_pen_up(ucb))) { | 196 | if (ucb->irq_pending) { |
| 197 | ucb->irq_pending = 0; | ||
| 198 | ucb1400_handle_pending_irq(ucb); | ||
| 199 | } | ||
| 204 | 200 | ||
| 205 | ucb1400_adc_enable(ucb->ac97); | 201 | ucb1400_adc_enable(ucb->ac97); |
| 206 | x = ucb1400_ts_read_xpos(ucb); | 202 | x = ucb1400_ts_read_xpos(ucb); |
| @@ -208,62 +204,91 @@ static irqreturn_t ucb1400_irq(int irqnr, void *devid) | |||
| 208 | p = ucb1400_ts_read_pressure(ucb); | 204 | p = ucb1400_ts_read_pressure(ucb); |
| 209 | ucb1400_adc_disable(ucb->ac97); | 205 | ucb1400_adc_disable(ucb->ac97); |
| 210 | 206 | ||
| 211 | ucb1400_ts_report_event(ucb->ts_idev, p, x, y); | ||
| 212 | |||
| 213 | wait_event_timeout(ucb->ts_wait, ucb->stopped, | ||
| 214 | msecs_to_jiffies(UCB1400_TS_POLL_PERIOD)); | ||
| 215 | } | ||
| 216 | |||
| 217 | ucb1400_ts_event_release(ucb->ts_idev); | ||
| 218 | |||
| 219 | if (!ucb->stopped) { | ||
| 220 | /* Switch back to interrupt mode. */ | 207 | /* Switch back to interrupt mode. */ |
| 221 | ucb1400_ts_mode_int(ucb); | 208 | ucb1400_ts_mode_int(ucb->ac97); |
| 222 | ucb1400_ts_irq_enable(ucb); | 209 | |
| 223 | } | 210 | msleep(10); |
| 211 | |||
| 212 | if (ucb1400_ts_pen_up(ucb->ac97)) { | ||
| 213 | ucb1400_ts_irq_enable(ucb->ac97); | ||
| 214 | |||
| 215 | /* | ||
| 216 | * If we spat out a valid sample set last time, | ||
| 217 | * spit out a "pen off" sample here. | ||
| 218 | */ | ||
| 219 | if (valid) { | ||
| 220 | ucb1400_ts_event_release(ucb->ts_idev); | ||
| 221 | valid = 0; | ||
| 222 | } | ||
| 223 | |||
| 224 | timeout = MAX_SCHEDULE_TIMEOUT; | ||
| 225 | } else { | ||
| 226 | valid = 1; | ||
| 227 | ucb1400_ts_evt_add(ucb->ts_idev, p, x, y); | ||
| 228 | timeout = msecs_to_jiffies(10); | ||
| 229 | } | ||
| 224 | 230 | ||
| 225 | return IRQ_HANDLED; | 231 | wait_event_freezable_timeout(ucb->ts_wait, |
| 226 | } | 232 | ucb->irq_pending || ucb->ts_restart || |
| 233 | kthread_should_stop(), timeout); | ||
| 234 | } | ||
| 227 | 235 | ||
| 228 | static void ucb1400_ts_stop(struct ucb1400_ts *ucb) | 236 | /* Send the "pen off" if we are stopping with the pen still active */ |
| 229 | { | 237 | if (valid) |
| 230 | /* Signal IRQ thread to stop polling and disable the handler. */ | 238 | ucb1400_ts_event_release(ucb->ts_idev); |
| 231 | ucb->stopped = true; | ||
| 232 | mb(); | ||
| 233 | wake_up(&ucb->ts_wait); | ||
| 234 | disable_irq(ucb->irq); | ||
| 235 | 239 | ||
| 236 | ucb1400_ts_irq_disable(ucb); | 240 | ucb->ts_task = NULL; |
| 237 | ucb1400_reg_write(ucb->ac97, UCB_TS_CR, 0); | 241 | return 0; |
| 238 | } | 242 | } |
| 239 | 243 | ||
| 240 | /* Must be called with ts->lock held */ | 244 | /* |
| 241 | static void ucb1400_ts_start(struct ucb1400_ts *ucb) | 245 | * A restriction with interrupts exists when using the ucb1400, as |
| 246 | * the codec read/write routines may sleep while waiting for codec | ||
| 247 | * access completion and uses semaphores for access control to the | ||
| 248 | * AC97 bus. A complete codec read cycle could take anywhere from | ||
| 249 | * 60 to 100uSec so we *definitely* don't want to spin inside the | ||
| 250 | * interrupt handler waiting for codec access. So, we handle the | ||
| 251 | * interrupt by scheduling a RT kernel thread to run in process | ||
| 252 | * context instead of interrupt context. | ||
| 253 | */ | ||
| 254 | static irqreturn_t ucb1400_hard_irq(int irqnr, void *devid) | ||
| 242 | { | 255 | { |
| 243 | /* Tell IRQ thread that it may poll the device. */ | 256 | struct ucb1400_ts *ucb = devid; |
| 244 | ucb->stopped = false; | ||
| 245 | mb(); | ||
| 246 | |||
| 247 | ucb1400_ts_mode_int(ucb); | ||
| 248 | ucb1400_ts_irq_enable(ucb); | ||
| 249 | 257 | ||
| 250 | enable_irq(ucb->irq); | 258 | if (irqnr == ucb->irq) { |
| 259 | disable_irq_nosync(ucb->irq); | ||
| 260 | ucb->irq_pending = 1; | ||
| 261 | wake_up(&ucb->ts_wait); | ||
| 262 | return IRQ_HANDLED; | ||
| 263 | } | ||
| 264 | return IRQ_NONE; | ||
| 251 | } | 265 | } |
| 252 | 266 | ||
| 253 | static int ucb1400_ts_open(struct input_dev *idev) | 267 | static int ucb1400_ts_open(struct input_dev *idev) |
| 254 | { | 268 | { |
| 255 | struct ucb1400_ts *ucb = input_get_drvdata(idev); | 269 | struct ucb1400_ts *ucb = input_get_drvdata(idev); |
| 270 | int ret = 0; | ||
| 256 | 271 | ||
| 257 | ucb1400_ts_start(ucb); | 272 | BUG_ON(ucb->ts_task); |
| 258 | 273 | ||
| 259 | return 0; | 274 | ucb->ts_task = kthread_run(ucb1400_ts_thread, ucb, "UCB1400_ts"); |
| 275 | if (IS_ERR(ucb->ts_task)) { | ||
| 276 | ret = PTR_ERR(ucb->ts_task); | ||
| 277 | ucb->ts_task = NULL; | ||
| 278 | } | ||
| 279 | |||
| 280 | return ret; | ||
| 260 | } | 281 | } |
| 261 | 282 | ||
| 262 | static void ucb1400_ts_close(struct input_dev *idev) | 283 | static void ucb1400_ts_close(struct input_dev *idev) |
| 263 | { | 284 | { |
| 264 | struct ucb1400_ts *ucb = input_get_drvdata(idev); | 285 | struct ucb1400_ts *ucb = input_get_drvdata(idev); |
| 265 | 286 | ||
| 266 | ucb1400_ts_stop(ucb); | 287 | if (ucb->ts_task) |
| 288 | kthread_stop(ucb->ts_task); | ||
| 289 | |||
| 290 | ucb1400_ts_irq_disable(ucb->ac97); | ||
| 291 | ucb1400_reg_write(ucb->ac97, UCB_TS_CR, 0); | ||
| 267 | } | 292 | } |
| 268 | 293 | ||
| 269 | #ifndef NO_IRQ | 294 | #ifndef NO_IRQ |
| @@ -274,8 +299,7 @@ static void ucb1400_ts_close(struct input_dev *idev) | |||
| 274 | * Try to probe our interrupt, rather than relying on lots of | 299 | * Try to probe our interrupt, rather than relying on lots of |
| 275 | * hard-coded machine dependencies. | 300 | * hard-coded machine dependencies. |
| 276 | */ | 301 | */ |
| 277 | static int ucb1400_ts_detect_irq(struct ucb1400_ts *ucb, | 302 | static int ucb1400_ts_detect_irq(struct ucb1400_ts *ucb) |
| 278 | struct platform_device *pdev) | ||
| 279 | { | 303 | { |
| 280 | unsigned long mask, timeout; | 304 | unsigned long mask, timeout; |
| 281 | 305 | ||
| @@ -297,7 +321,7 @@ static int ucb1400_ts_detect_irq(struct ucb1400_ts *ucb, | |||
| 297 | UCB_ADC_DAT_VALID)) { | 321 | UCB_ADC_DAT_VALID)) { |
| 298 | cpu_relax(); | 322 | cpu_relax(); |
| 299 | if (time_after(jiffies, timeout)) { | 323 | if (time_after(jiffies, timeout)) { |
| 300 | dev_err(&pdev->dev, "timed out in IRQ probe\n"); | 324 | printk(KERN_ERR "ucb1400: timed out in IRQ probe\n"); |
| 301 | probe_irq_off(mask); | 325 | probe_irq_off(mask); |
| 302 | return -ENODEV; | 326 | return -ENODEV; |
| 303 | } | 327 | } |
| @@ -318,11 +342,11 @@ static int ucb1400_ts_detect_irq(struct ucb1400_ts *ucb, | |||
| 318 | return 0; | 342 | return 0; |
| 319 | } | 343 | } |
| 320 | 344 | ||
| 321 | static int ucb1400_ts_probe(struct platform_device *pdev) | 345 | static int ucb1400_ts_probe(struct platform_device *dev) |
| 322 | { | 346 | { |
| 323 | struct ucb1400_ts *ucb = pdev->dev.platform_data; | ||
| 324 | int error, x_res, y_res; | 347 | int error, x_res, y_res; |
| 325 | u16 fcsr; | 348 | u16 fcsr; |
| 349 | struct ucb1400_ts *ucb = dev->dev.platform_data; | ||
| 326 | 350 | ||
| 327 | ucb->ts_idev = input_allocate_device(); | 351 | ucb->ts_idev = input_allocate_device(); |
| 328 | if (!ucb->ts_idev) { | 352 | if (!ucb->ts_idev) { |
| @@ -332,19 +356,27 @@ static int ucb1400_ts_probe(struct platform_device *pdev) | |||
| 332 | 356 | ||
| 333 | /* Only in case the IRQ line wasn't supplied, try detecting it */ | 357 | /* Only in case the IRQ line wasn't supplied, try detecting it */ |
| 334 | if (ucb->irq < 0) { | 358 | if (ucb->irq < 0) { |
| 335 | error = ucb1400_ts_detect_irq(ucb, pdev); | 359 | error = ucb1400_ts_detect_irq(ucb); |
| 336 | if (error) { | 360 | if (error) { |
| 337 | dev_err(&pdev->dev, "IRQ probe failed\n"); | 361 | printk(KERN_ERR "UCB1400: IRQ probe failed\n"); |
| 338 | goto err_free_devs; | 362 | goto err_free_devs; |
| 339 | } | 363 | } |
| 340 | } | 364 | } |
| 341 | dev_dbg(&pdev->dev, "found IRQ %d\n", ucb->irq); | ||
| 342 | 365 | ||
| 343 | init_waitqueue_head(&ucb->ts_wait); | 366 | init_waitqueue_head(&ucb->ts_wait); |
| 344 | 367 | ||
| 368 | error = request_irq(ucb->irq, ucb1400_hard_irq, IRQF_TRIGGER_RISING, | ||
| 369 | "UCB1400", ucb); | ||
| 370 | if (error) { | ||
| 371 | printk(KERN_ERR "ucb1400: unable to grab irq%d: %d\n", | ||
| 372 | ucb->irq, error); | ||
| 373 | goto err_free_devs; | ||
| 374 | } | ||
| 375 | printk(KERN_DEBUG "UCB1400: found IRQ %d\n", ucb->irq); | ||
| 376 | |||
| 345 | input_set_drvdata(ucb->ts_idev, ucb); | 377 | input_set_drvdata(ucb->ts_idev, ucb); |
| 346 | 378 | ||
| 347 | ucb->ts_idev->dev.parent = &pdev->dev; | 379 | ucb->ts_idev->dev.parent = &dev->dev; |
| 348 | ucb->ts_idev->name = "UCB1400 touchscreen interface"; | 380 | ucb->ts_idev->name = "UCB1400 touchscreen interface"; |
| 349 | ucb->ts_idev->id.vendor = ucb1400_reg_read(ucb->ac97, | 381 | ucb->ts_idev->id.vendor = ucb1400_reg_read(ucb->ac97, |
| 350 | AC97_VENDOR_ID1); | 382 | AC97_VENDOR_ID1); |
| @@ -366,23 +398,12 @@ static int ucb1400_ts_probe(struct platform_device *pdev) | |||
| 366 | x_res = ucb1400_ts_read_xres(ucb); | 398 | x_res = ucb1400_ts_read_xres(ucb); |
| 367 | y_res = ucb1400_ts_read_yres(ucb); | 399 | y_res = ucb1400_ts_read_yres(ucb); |
| 368 | ucb1400_adc_disable(ucb->ac97); | 400 | ucb1400_adc_disable(ucb->ac97); |
| 369 | dev_dbg(&pdev->dev, "x/y = %d/%d\n", x_res, y_res); | 401 | printk(KERN_DEBUG "UCB1400: x/y = %d/%d\n", x_res, y_res); |
| 370 | 402 | ||
| 371 | input_set_abs_params(ucb->ts_idev, ABS_X, 0, x_res, 0, 0); | 403 | input_set_abs_params(ucb->ts_idev, ABS_X, 0, x_res, 0, 0); |
| 372 | input_set_abs_params(ucb->ts_idev, ABS_Y, 0, y_res, 0, 0); | 404 | input_set_abs_params(ucb->ts_idev, ABS_Y, 0, y_res, 0, 0); |
| 373 | input_set_abs_params(ucb->ts_idev, ABS_PRESSURE, 0, 0, 0, 0); | 405 | input_set_abs_params(ucb->ts_idev, ABS_PRESSURE, 0, 0, 0, 0); |
| 374 | 406 | ||
| 375 | ucb1400_ts_stop(ucb); | ||
| 376 | |||
| 377 | error = request_threaded_irq(ucb->irq, NULL, ucb1400_irq, | ||
| 378 | IRQF_TRIGGER_RISING | IRQF_ONESHOT, | ||
| 379 | "UCB1400", ucb); | ||
| 380 | if (error) { | ||
| 381 | dev_err(&pdev->dev, | ||
| 382 | "unable to grab irq%d: %d\n", ucb->irq, error); | ||
| 383 | goto err_free_devs; | ||
| 384 | } | ||
| 385 | |||
| 386 | error = input_register_device(ucb->ts_idev); | 407 | error = input_register_device(ucb->ts_idev); |
| 387 | if (error) | 408 | if (error) |
| 388 | goto err_free_irq; | 409 | goto err_free_irq; |
| @@ -395,61 +416,56 @@ err_free_devs: | |||
| 395 | input_free_device(ucb->ts_idev); | 416 | input_free_device(ucb->ts_idev); |
| 396 | err: | 417 | err: |
| 397 | return error; | 418 | return error; |
| 419 | |||
| 398 | } | 420 | } |
| 399 | 421 | ||
| 400 | static int ucb1400_ts_remove(struct platform_device *pdev) | 422 | static int ucb1400_ts_remove(struct platform_device *dev) |
| 401 | { | 423 | { |
| 402 | struct ucb1400_ts *ucb = pdev->dev.platform_data; | 424 | struct ucb1400_ts *ucb = dev->dev.platform_data; |
| 403 | 425 | ||
| 404 | free_irq(ucb->irq, ucb); | 426 | free_irq(ucb->irq, ucb); |
| 405 | input_unregister_device(ucb->ts_idev); | 427 | input_unregister_device(ucb->ts_idev); |
| 406 | |||
| 407 | return 0; | ||
| 408 | } | ||
| 409 | |||
| 410 | #ifdef CONFIG_PM_SLEEP | ||
| 411 | static int ucb1400_ts_suspend(struct device *dev) | ||
| 412 | { | ||
| 413 | struct ucb1400_ts *ucb = dev->platform_data; | ||
| 414 | struct input_dev *idev = ucb->ts_idev; | ||
| 415 | |||
| 416 | mutex_lock(&idev->mutex); | ||
| 417 | |||
| 418 | if (idev->users) | ||
| 419 | ucb1400_ts_start(ucb); | ||
| 420 | |||
| 421 | mutex_unlock(&idev->mutex); | ||
| 422 | return 0; | 428 | return 0; |
| 423 | } | 429 | } |
| 424 | 430 | ||
| 425 | static int ucb1400_ts_resume(struct device *dev) | 431 | #ifdef CONFIG_PM |
| 432 | static int ucb1400_ts_resume(struct platform_device *dev) | ||
| 426 | { | 433 | { |
| 427 | struct ucb1400_ts *ucb = dev->platform_data; | 434 | struct ucb1400_ts *ucb = dev->dev.platform_data; |
| 428 | struct input_dev *idev = ucb->ts_idev; | 435 | |
| 429 | 436 | if (ucb->ts_task) { | |
| 430 | mutex_lock(&idev->mutex); | 437 | /* |
| 431 | 438 | * Restart the TS thread to ensure the | |
| 432 | if (idev->users) | 439 | * TS interrupt mode is set up again |
| 433 | ucb1400_ts_stop(ucb); | 440 | * after sleep. |
| 434 | 441 | */ | |
| 435 | mutex_unlock(&idev->mutex); | 442 | ucb->ts_restart = 1; |
| 443 | wake_up(&ucb->ts_wait); | ||
| 444 | } | ||
| 436 | return 0; | 445 | return 0; |
| 437 | } | 446 | } |
| 447 | #else | ||
| 448 | #define ucb1400_ts_resume NULL | ||
| 438 | #endif | 449 | #endif |
| 439 | 450 | ||
| 440 | static SIMPLE_DEV_PM_OPS(ucb1400_ts_pm_ops, | ||
| 441 | ucb1400_ts_suspend, ucb1400_ts_resume); | ||
| 442 | |||
| 443 | static struct platform_driver ucb1400_ts_driver = { | 451 | static struct platform_driver ucb1400_ts_driver = { |
| 444 | .probe = ucb1400_ts_probe, | 452 | .probe = ucb1400_ts_probe, |
| 445 | .remove = ucb1400_ts_remove, | 453 | .remove = ucb1400_ts_remove, |
| 454 | .resume = ucb1400_ts_resume, | ||
| 446 | .driver = { | 455 | .driver = { |
| 447 | .name = "ucb1400_ts", | 456 | .name = "ucb1400_ts", |
| 448 | .owner = THIS_MODULE, | ||
| 449 | .pm = &ucb1400_ts_pm_ops, | ||
| 450 | }, | 457 | }, |
| 451 | }; | 458 | }; |
| 452 | module_platform_driver(ucb1400_ts_driver); | 459 | |
| 460 | static int __init ucb1400_ts_init(void) | ||
| 461 | { | ||
| 462 | return platform_driver_register(&ucb1400_ts_driver); | ||
| 463 | } | ||
| 464 | |||
| 465 | static void __exit ucb1400_ts_exit(void) | ||
| 466 | { | ||
| 467 | platform_driver_unregister(&ucb1400_ts_driver); | ||
| 468 | } | ||
| 453 | 469 | ||
| 454 | module_param(adcsync, bool, 0444); | 470 | module_param(adcsync, bool, 0444); |
| 455 | MODULE_PARM_DESC(adcsync, "Synchronize touch readings with ADCSYNC pin."); | 471 | MODULE_PARM_DESC(adcsync, "Synchronize touch readings with ADCSYNC pin."); |
| @@ -463,5 +479,8 @@ MODULE_PARM_DESC(ts_delay_pressure, | |||
| 463 | "delay between panel setup and pressure read." | 479 | "delay between panel setup and pressure read." |
| 464 | " Default = 0us."); | 480 | " Default = 0us."); |
| 465 | 481 | ||
| 482 | module_init(ucb1400_ts_init); | ||
| 483 | module_exit(ucb1400_ts_exit); | ||
| 484 | |||
| 466 | MODULE_DESCRIPTION("Philips UCB1400 touchscreen driver"); | 485 | MODULE_DESCRIPTION("Philips UCB1400 touchscreen driver"); |
| 467 | MODULE_LICENSE("GPL"); | 486 | MODULE_LICENSE("GPL"); |
diff --git a/drivers/input/touchscreen/usbtouchscreen.c b/drivers/input/touchscreen/usbtouchscreen.c index 721fdb3597c..73fd6642b68 100644 --- a/drivers/input/touchscreen/usbtouchscreen.c +++ b/drivers/input/touchscreen/usbtouchscreen.c | |||
| @@ -16,8 +16,6 @@ | |||
| 16 | * - JASTEC USB touch controller/DigiTech DTR-02U | 16 | * - JASTEC USB touch controller/DigiTech DTR-02U |
| 17 | * - Zytronic capacitive touchscreen | 17 | * - Zytronic capacitive touchscreen |
| 18 | * - NEXIO/iNexio | 18 | * - NEXIO/iNexio |
| 19 | * - Elo TouchSystems 2700 IntelliTouch | ||
| 20 | * - EasyTouch USB Dual/Multi touch controller from Data Modul | ||
| 21 | * | 19 | * |
| 22 | * Copyright (C) 2004-2007 by Daniel Ritz <daniel.ritz@gmx.ch> | 20 | * Copyright (C) 2004-2007 by Daniel Ritz <daniel.ritz@gmx.ch> |
| 23 | * Copyright (C) by Todd E. Johnson (mtouchusb.c) | 21 | * Copyright (C) by Todd E. Johnson (mtouchusb.c) |
| @@ -61,11 +59,11 @@ | |||
| 61 | #define DRIVER_AUTHOR "Daniel Ritz <daniel.ritz@gmx.ch>" | 59 | #define DRIVER_AUTHOR "Daniel Ritz <daniel.ritz@gmx.ch>" |
| 62 | #define DRIVER_DESC "USB Touchscreen Driver" | 60 | #define DRIVER_DESC "USB Touchscreen Driver" |
| 63 | 61 | ||
| 64 | static bool swap_xy; | 62 | static int swap_xy; |
| 65 | module_param(swap_xy, bool, 0644); | 63 | module_param(swap_xy, bool, 0644); |
| 66 | MODULE_PARM_DESC(swap_xy, "If set X and Y axes are swapped."); | 64 | MODULE_PARM_DESC(swap_xy, "If set X and Y axes are swapped."); |
| 67 | 65 | ||
| 68 | static bool hwcalib_xy; | 66 | static int hwcalib_xy; |
| 69 | module_param(hwcalib_xy, bool, 0644); | 67 | module_param(hwcalib_xy, bool, 0644); |
| 70 | MODULE_PARM_DESC(hwcalib_xy, "If set hw-calibrated X/Y are used if available"); | 68 | MODULE_PARM_DESC(hwcalib_xy, "If set hw-calibrated X/Y are used if available"); |
| 71 | 69 | ||
| @@ -140,8 +138,6 @@ enum { | |||
| 140 | DEVTYPE_ZYTRONIC, | 138 | DEVTYPE_ZYTRONIC, |
| 141 | DEVTYPE_TC45USB, | 139 | DEVTYPE_TC45USB, |
| 142 | DEVTYPE_NEXIO, | 140 | DEVTYPE_NEXIO, |
| 143 | DEVTYPE_ELO, | ||
| 144 | DEVTYPE_ETOUCH, | ||
| 145 | }; | 141 | }; |
| 146 | 142 | ||
| 147 | #define USB_DEVICE_HID_CLASS(vend, prod) \ | 143 | #define USB_DEVICE_HID_CLASS(vend, prod) \ |
| @@ -243,14 +239,6 @@ static const struct usb_device_id usbtouch_devices[] = { | |||
| 243 | .driver_info = DEVTYPE_NEXIO}, | 239 | .driver_info = DEVTYPE_NEXIO}, |
| 244 | #endif | 240 | #endif |
| 245 | 241 | ||
| 246 | #ifdef CONFIG_TOUCHSCREEN_USB_ELO | ||
| 247 | {USB_DEVICE(0x04e7, 0x0020), .driver_info = DEVTYPE_ELO}, | ||
| 248 | #endif | ||
| 249 | |||
| 250 | #ifdef CONFIG_TOUCHSCREEN_USB_EASYTOUCH | ||
| 251 | {USB_DEVICE(0x7374, 0x0001), .driver_info = DEVTYPE_ETOUCH}, | ||
| 252 | #endif | ||
| 253 | |||
| 254 | {} | 242 | {} |
| 255 | }; | 243 | }; |
| 256 | 244 | ||
| @@ -269,9 +257,8 @@ static int e2i_init(struct usbtouch_usb *usbtouch) | |||
| 269 | 0x01, 0x02, 0x0000, 0x0081, | 257 | 0x01, 0x02, 0x0000, 0x0081, |
| 270 | NULL, 0, USB_CTRL_SET_TIMEOUT); | 258 | NULL, 0, USB_CTRL_SET_TIMEOUT); |
| 271 | 259 | ||
| 272 | dev_dbg(&usbtouch->interface->dev, | 260 | dbg("%s - usb_control_msg - E2I_RESET - bytes|err: %d", |
| 273 | "%s - usb_control_msg - E2I_RESET - bytes|err: %d\n", | 261 | __func__, ret); |
| 274 | __func__, ret); | ||
| 275 | return ret; | 262 | return ret; |
| 276 | } | 263 | } |
| 277 | 264 | ||
| @@ -304,45 +291,6 @@ static int e2i_read_data(struct usbtouch_usb *dev, unsigned char *pkt) | |||
| 304 | #define EGALAX_PKT_TYPE_REPT 0x80 | 291 | #define EGALAX_PKT_TYPE_REPT 0x80 |
| 305 | #define EGALAX_PKT_TYPE_DIAG 0x0A | 292 | #define EGALAX_PKT_TYPE_DIAG 0x0A |
| 306 | 293 | ||
| 307 | static int egalax_init(struct usbtouch_usb *usbtouch) | ||
| 308 | { | ||
| 309 | int ret, i; | ||
| 310 | unsigned char *buf; | ||
| 311 | struct usb_device *udev = interface_to_usbdev(usbtouch->interface); | ||
| 312 | |||
| 313 | /* | ||
| 314 | * An eGalax diagnostic packet kicks the device into using the right | ||
| 315 | * protocol. We send a "check active" packet. The response will be | ||
| 316 | * read later and ignored. | ||
| 317 | */ | ||
| 318 | |||
| 319 | buf = kmalloc(3, GFP_KERNEL); | ||
| 320 | if (!buf) | ||
| 321 | return -ENOMEM; | ||
| 322 | |||
| 323 | buf[0] = EGALAX_PKT_TYPE_DIAG; | ||
| 324 | buf[1] = 1; /* length */ | ||
| 325 | buf[2] = 'A'; /* command - check active */ | ||
| 326 | |||
| 327 | for (i = 0; i < 3; i++) { | ||
| 328 | ret = usb_control_msg(udev, usb_sndctrlpipe(udev, 0), | ||
| 329 | 0, | ||
| 330 | USB_DIR_OUT | USB_TYPE_VENDOR | USB_RECIP_DEVICE, | ||
| 331 | 0, 0, buf, 3, | ||
| 332 | USB_CTRL_SET_TIMEOUT); | ||
| 333 | if (ret >= 0) { | ||
| 334 | ret = 0; | ||
| 335 | break; | ||
| 336 | } | ||
| 337 | if (ret != -EPIPE) | ||
| 338 | break; | ||
| 339 | } | ||
| 340 | |||
| 341 | kfree(buf); | ||
| 342 | |||
| 343 | return ret; | ||
| 344 | } | ||
| 345 | |||
| 346 | static int egalax_read_data(struct usbtouch_usb *dev, unsigned char *pkt) | 294 | static int egalax_read_data(struct usbtouch_usb *dev, unsigned char *pkt) |
| 347 | { | 295 | { |
| 348 | if ((pkt[0] & EGALAX_PKT_TYPE_MASK) != EGALAX_PKT_TYPE_REPT) | 296 | if ((pkt[0] & EGALAX_PKT_TYPE_MASK) != EGALAX_PKT_TYPE_REPT) |
| @@ -372,51 +320,6 @@ static int egalax_get_pkt_len(unsigned char *buf, int len) | |||
| 372 | } | 320 | } |
| 373 | #endif | 321 | #endif |
| 374 | 322 | ||
| 375 | /***************************************************************************** | ||
| 376 | * EasyTouch part | ||
| 377 | */ | ||
| 378 | |||
| 379 | #ifdef CONFIG_TOUCHSCREEN_USB_EASYTOUCH | ||
| 380 | |||
| 381 | #ifndef MULTI_PACKET | ||
| 382 | #define MULTI_PACKET | ||
| 383 | #endif | ||
| 384 | |||
| 385 | #define ETOUCH_PKT_TYPE_MASK 0xFE | ||
| 386 | #define ETOUCH_PKT_TYPE_REPT 0x80 | ||
| 387 | #define ETOUCH_PKT_TYPE_REPT2 0xB0 | ||
| 388 | #define ETOUCH_PKT_TYPE_DIAG 0x0A | ||
| 389 | |||
| 390 | static int etouch_read_data(struct usbtouch_usb *dev, unsigned char *pkt) | ||
| 391 | { | ||
| 392 | if ((pkt[0] & ETOUCH_PKT_TYPE_MASK) != ETOUCH_PKT_TYPE_REPT && | ||
| 393 | (pkt[0] & ETOUCH_PKT_TYPE_MASK) != ETOUCH_PKT_TYPE_REPT2) | ||
| 394 | return 0; | ||
| 395 | |||
| 396 | dev->x = ((pkt[1] & 0x1F) << 7) | (pkt[2] & 0x7F); | ||
| 397 | dev->y = ((pkt[3] & 0x1F) << 7) | (pkt[4] & 0x7F); | ||
| 398 | dev->touch = pkt[0] & 0x01; | ||
| 399 | |||
| 400 | return 1; | ||
| 401 | } | ||
| 402 | |||
| 403 | static int etouch_get_pkt_len(unsigned char *buf, int len) | ||
| 404 | { | ||
| 405 | switch (buf[0] & ETOUCH_PKT_TYPE_MASK) { | ||
| 406 | case ETOUCH_PKT_TYPE_REPT: | ||
| 407 | case ETOUCH_PKT_TYPE_REPT2: | ||
| 408 | return 5; | ||
| 409 | |||
| 410 | case ETOUCH_PKT_TYPE_DIAG: | ||
| 411 | if (len < 2) | ||
| 412 | return -1; | ||
| 413 | |||
| 414 | return buf[1] + 2; | ||
| 415 | } | ||
| 416 | |||
| 417 | return 0; | ||
| 418 | } | ||
| 419 | #endif | ||
| 420 | 323 | ||
| 421 | /***************************************************************************** | 324 | /***************************************************************************** |
| 422 | * PanJit Part | 325 | * PanJit Part |
| @@ -465,9 +368,8 @@ static int mtouch_init(struct usbtouch_usb *usbtouch) | |||
| 465 | MTOUCHUSB_RESET, | 368 | MTOUCHUSB_RESET, |
| 466 | USB_DIR_OUT | USB_TYPE_VENDOR | USB_RECIP_DEVICE, | 369 | USB_DIR_OUT | USB_TYPE_VENDOR | USB_RECIP_DEVICE, |
| 467 | 1, 0, NULL, 0, USB_CTRL_SET_TIMEOUT); | 370 | 1, 0, NULL, 0, USB_CTRL_SET_TIMEOUT); |
| 468 | dev_dbg(&usbtouch->interface->dev, | 371 | dbg("%s - usb_control_msg - MTOUCHUSB_RESET - bytes|err: %d", |
| 469 | "%s - usb_control_msg - MTOUCHUSB_RESET - bytes|err: %d\n", | 372 | __func__, ret); |
| 470 | __func__, ret); | ||
| 471 | if (ret < 0) | 373 | if (ret < 0) |
| 472 | return ret; | 374 | return ret; |
| 473 | msleep(150); | 375 | msleep(150); |
| @@ -477,9 +379,8 @@ static int mtouch_init(struct usbtouch_usb *usbtouch) | |||
| 477 | MTOUCHUSB_ASYNC_REPORT, | 379 | MTOUCHUSB_ASYNC_REPORT, |
| 478 | USB_DIR_OUT | USB_TYPE_VENDOR | USB_RECIP_DEVICE, | 380 | USB_DIR_OUT | USB_TYPE_VENDOR | USB_RECIP_DEVICE, |
| 479 | 1, 1, NULL, 0, USB_CTRL_SET_TIMEOUT); | 381 | 1, 1, NULL, 0, USB_CTRL_SET_TIMEOUT); |
| 480 | dev_dbg(&usbtouch->interface->dev, | 382 | dbg("%s - usb_control_msg - MTOUCHUSB_ASYNC_REPORT - bytes|err: %d", |
| 481 | "%s - usb_control_msg - MTOUCHUSB_ASYNC_REPORT - bytes|err: %d\n", | 383 | __func__, ret); |
| 482 | __func__, ret); | ||
| 483 | if (ret >= 0) | 384 | if (ret >= 0) |
| 484 | break; | 385 | break; |
| 485 | if (ret != -EPIPE) | 386 | if (ret != -EPIPE) |
| @@ -779,29 +680,27 @@ static int jastec_read_data(struct usbtouch_usb *dev, unsigned char *pkt) | |||
| 779 | #ifdef CONFIG_TOUCHSCREEN_USB_ZYTRONIC | 680 | #ifdef CONFIG_TOUCHSCREEN_USB_ZYTRONIC |
| 780 | static int zytronic_read_data(struct usbtouch_usb *dev, unsigned char *pkt) | 681 | static int zytronic_read_data(struct usbtouch_usb *dev, unsigned char *pkt) |
| 781 | { | 682 | { |
| 782 | struct usb_interface *intf = dev->interface; | ||
| 783 | |||
| 784 | switch (pkt[0]) { | 683 | switch (pkt[0]) { |
| 785 | case 0x3A: /* command response */ | 684 | case 0x3A: /* command response */ |
| 786 | dev_dbg(&intf->dev, "%s: Command response %d\n", __func__, pkt[1]); | 685 | dbg("%s: Command response %d", __func__, pkt[1]); |
| 787 | break; | 686 | break; |
| 788 | 687 | ||
| 789 | case 0xC0: /* down */ | 688 | case 0xC0: /* down */ |
| 790 | dev->x = (pkt[1] & 0x7f) | ((pkt[2] & 0x07) << 7); | 689 | dev->x = (pkt[1] & 0x7f) | ((pkt[2] & 0x07) << 7); |
| 791 | dev->y = (pkt[3] & 0x7f) | ((pkt[4] & 0x07) << 7); | 690 | dev->y = (pkt[3] & 0x7f) | ((pkt[4] & 0x07) << 7); |
| 792 | dev->touch = 1; | 691 | dev->touch = 1; |
| 793 | dev_dbg(&intf->dev, "%s: down %d,%d\n", __func__, dev->x, dev->y); | 692 | dbg("%s: down %d,%d", __func__, dev->x, dev->y); |
| 794 | return 1; | 693 | return 1; |
| 795 | 694 | ||
| 796 | case 0x80: /* up */ | 695 | case 0x80: /* up */ |
| 797 | dev->x = (pkt[1] & 0x7f) | ((pkt[2] & 0x07) << 7); | 696 | dev->x = (pkt[1] & 0x7f) | ((pkt[2] & 0x07) << 7); |
| 798 | dev->y = (pkt[3] & 0x7f) | ((pkt[4] & 0x07) << 7); | 697 | dev->y = (pkt[3] & 0x7f) | ((pkt[4] & 0x07) << 7); |
| 799 | dev->touch = 0; | 698 | dev->touch = 0; |
| 800 | dev_dbg(&intf->dev, "%s: up %d,%d\n", __func__, dev->x, dev->y); | 699 | dbg("%s: up %d,%d", __func__, dev->x, dev->y); |
| 801 | return 1; | 700 | return 1; |
| 802 | 701 | ||
| 803 | default: | 702 | default: |
| 804 | dev_dbg(&intf->dev, "%s: Unknown return %d\n", __func__, pkt[0]); | 703 | dbg("%s: Unknown return %d", __func__, pkt[0]); |
| 805 | break; | 704 | break; |
| 806 | } | 705 | } |
| 807 | 706 | ||
| @@ -856,8 +755,7 @@ static int nexio_alloc(struct usbtouch_usb *usbtouch) | |||
| 856 | 755 | ||
| 857 | priv->ack = usb_alloc_urb(0, GFP_KERNEL); | 756 | priv->ack = usb_alloc_urb(0, GFP_KERNEL); |
| 858 | if (!priv->ack) { | 757 | if (!priv->ack) { |
| 859 | dev_dbg(&usbtouch->interface->dev, | 758 | dbg("%s - usb_alloc_urb failed: usbtouch->ack", __func__); |
| 860 | "%s - usb_alloc_urb failed: usbtouch->ack\n", __func__); | ||
| 861 | goto err_ack_buf; | 759 | goto err_ack_buf; |
| 862 | } | 760 | } |
| 863 | 761 | ||
| @@ -1047,24 +945,6 @@ static int nexio_read_data(struct usbtouch_usb *usbtouch, unsigned char *pkt) | |||
| 1047 | 945 | ||
| 1048 | 946 | ||
| 1049 | /***************************************************************************** | 947 | /***************************************************************************** |
| 1050 | * ELO part | ||
| 1051 | */ | ||
| 1052 | |||
| 1053 | #ifdef CONFIG_TOUCHSCREEN_USB_ELO | ||
| 1054 | |||
| 1055 | static int elo_read_data(struct usbtouch_usb *dev, unsigned char *pkt) | ||
| 1056 | { | ||
| 1057 | dev->x = (pkt[3] << 8) | pkt[2]; | ||
| 1058 | dev->y = (pkt[5] << 8) | pkt[4]; | ||
| 1059 | dev->touch = pkt[6] > 0; | ||
| 1060 | dev->press = pkt[6]; | ||
| 1061 | |||
| 1062 | return 1; | ||
| 1063 | } | ||
| 1064 | #endif | ||
| 1065 | |||
| 1066 | |||
| 1067 | /***************************************************************************** | ||
| 1068 | * the different device descriptors | 948 | * the different device descriptors |
| 1069 | */ | 949 | */ |
| 1070 | #ifdef MULTI_PACKET | 950 | #ifdef MULTI_PACKET |
| @@ -1073,18 +953,6 @@ static void usbtouch_process_multi(struct usbtouch_usb *usbtouch, | |||
| 1073 | #endif | 953 | #endif |
| 1074 | 954 | ||
| 1075 | static struct usbtouch_device_info usbtouch_dev_info[] = { | 955 | static struct usbtouch_device_info usbtouch_dev_info[] = { |
| 1076 | #ifdef CONFIG_TOUCHSCREEN_USB_ELO | ||
| 1077 | [DEVTYPE_ELO] = { | ||
| 1078 | .min_xc = 0x0, | ||
| 1079 | .max_xc = 0x0fff, | ||
| 1080 | .min_yc = 0x0, | ||
| 1081 | .max_yc = 0x0fff, | ||
| 1082 | .max_press = 0xff, | ||
| 1083 | .rept_size = 8, | ||
| 1084 | .read_data = elo_read_data, | ||
| 1085 | }, | ||
| 1086 | #endif | ||
| 1087 | |||
| 1088 | #ifdef CONFIG_TOUCHSCREEN_USB_EGALAX | 956 | #ifdef CONFIG_TOUCHSCREEN_USB_EGALAX |
| 1089 | [DEVTYPE_EGALAX] = { | 957 | [DEVTYPE_EGALAX] = { |
| 1090 | .min_xc = 0x0, | 958 | .min_xc = 0x0, |
| @@ -1095,7 +963,6 @@ static struct usbtouch_device_info usbtouch_dev_info[] = { | |||
| 1095 | .process_pkt = usbtouch_process_multi, | 963 | .process_pkt = usbtouch_process_multi, |
| 1096 | .get_pkt_len = egalax_get_pkt_len, | 964 | .get_pkt_len = egalax_get_pkt_len, |
| 1097 | .read_data = egalax_read_data, | 965 | .read_data = egalax_read_data, |
| 1098 | .init = egalax_init, | ||
| 1099 | }, | 966 | }, |
| 1100 | #endif | 967 | #endif |
| 1101 | 968 | ||
| @@ -1272,18 +1139,6 @@ static struct usbtouch_device_info usbtouch_dev_info[] = { | |||
| 1272 | .exit = nexio_exit, | 1139 | .exit = nexio_exit, |
| 1273 | }, | 1140 | }, |
| 1274 | #endif | 1141 | #endif |
| 1275 | #ifdef CONFIG_TOUCHSCREEN_USB_EASYTOUCH | ||
| 1276 | [DEVTYPE_ETOUCH] = { | ||
| 1277 | .min_xc = 0x0, | ||
| 1278 | .max_xc = 0x07ff, | ||
| 1279 | .min_yc = 0x0, | ||
| 1280 | .max_yc = 0x07ff, | ||
| 1281 | .rept_size = 16, | ||
| 1282 | .process_pkt = usbtouch_process_multi, | ||
| 1283 | .get_pkt_len = etouch_get_pkt_len, | ||
| 1284 | .read_data = etouch_read_data, | ||
| 1285 | }, | ||
| 1286 | #endif | ||
| 1287 | }; | 1142 | }; |
| 1288 | 1143 | ||
| 1289 | 1144 | ||
| @@ -1395,7 +1250,6 @@ out_flush_buf: | |||
| 1395 | static void usbtouch_irq(struct urb *urb) | 1250 | static void usbtouch_irq(struct urb *urb) |
| 1396 | { | 1251 | { |
| 1397 | struct usbtouch_usb *usbtouch = urb->context; | 1252 | struct usbtouch_usb *usbtouch = urb->context; |
| 1398 | struct device *dev = &usbtouch->interface->dev; | ||
| 1399 | int retval; | 1253 | int retval; |
| 1400 | 1254 | ||
| 1401 | switch (urb->status) { | 1255 | switch (urb->status) { |
| @@ -1404,21 +1258,20 @@ static void usbtouch_irq(struct urb *urb) | |||
| 1404 | break; | 1258 | break; |
| 1405 | case -ETIME: | 1259 | case -ETIME: |
| 1406 | /* this urb is timing out */ | 1260 | /* this urb is timing out */ |
| 1407 | dev_dbg(dev, | 1261 | dbg("%s - urb timed out - was the device unplugged?", |
| 1408 | "%s - urb timed out - was the device unplugged?\n", | 1262 | __func__); |
| 1409 | __func__); | ||
| 1410 | return; | 1263 | return; |
| 1411 | case -ECONNRESET: | 1264 | case -ECONNRESET: |
| 1412 | case -ENOENT: | 1265 | case -ENOENT: |
| 1413 | case -ESHUTDOWN: | 1266 | case -ESHUTDOWN: |
| 1414 | case -EPIPE: | 1267 | case -EPIPE: |
| 1415 | /* this urb is terminated, clean up */ | 1268 | /* this urb is terminated, clean up */ |
| 1416 | dev_dbg(dev, "%s - urb shutting down with status: %d\n", | 1269 | dbg("%s - urb shutting down with status: %d", |
| 1417 | __func__, urb->status); | 1270 | __func__, urb->status); |
| 1418 | return; | 1271 | return; |
| 1419 | default: | 1272 | default: |
| 1420 | dev_dbg(dev, "%s - nonzero urb status received: %d\n", | 1273 | dbg("%s - nonzero urb status received: %d", |
| 1421 | __func__, urb->status); | 1274 | __func__, urb->status); |
| 1422 | goto exit; | 1275 | goto exit; |
| 1423 | } | 1276 | } |
| 1424 | 1277 | ||
| @@ -1428,8 +1281,8 @@ exit: | |||
| 1428 | usb_mark_last_busy(interface_to_usbdev(usbtouch->interface)); | 1281 | usb_mark_last_busy(interface_to_usbdev(usbtouch->interface)); |
| 1429 | retval = usb_submit_urb(urb, GFP_ATOMIC); | 1282 | retval = usb_submit_urb(urb, GFP_ATOMIC); |
| 1430 | if (retval) | 1283 | if (retval) |
| 1431 | dev_err(dev, "%s - usb_submit_urb failed with result: %d\n", | 1284 | err("%s - usb_submit_urb failed with result: %d", |
| 1432 | __func__, retval); | 1285 | __func__, retval); |
| 1433 | } | 1286 | } |
| 1434 | 1287 | ||
| 1435 | static int usbtouch_open(struct input_dev *input) | 1288 | static int usbtouch_open(struct input_dev *input) |
| @@ -1504,9 +1357,8 @@ static int usbtouch_reset_resume(struct usb_interface *intf) | |||
| 1504 | if (usbtouch->type->init) { | 1357 | if (usbtouch->type->init) { |
| 1505 | err = usbtouch->type->init(usbtouch); | 1358 | err = usbtouch->type->init(usbtouch); |
| 1506 | if (err) { | 1359 | if (err) { |
| 1507 | dev_dbg(&intf->dev, | 1360 | dbg("%s - type->init() failed, err: %d", |
| 1508 | "%s - type->init() failed, err: %d\n", | 1361 | __func__, err); |
| 1509 | __func__, err); | ||
| 1510 | return err; | 1362 | return err; |
| 1511 | } | 1363 | } |
| 1512 | } | 1364 | } |
| @@ -1581,8 +1433,7 @@ static int usbtouch_probe(struct usb_interface *intf, | |||
| 1581 | 1433 | ||
| 1582 | usbtouch->irq = usb_alloc_urb(0, GFP_KERNEL); | 1434 | usbtouch->irq = usb_alloc_urb(0, GFP_KERNEL); |
| 1583 | if (!usbtouch->irq) { | 1435 | if (!usbtouch->irq) { |
| 1584 | dev_dbg(&intf->dev, | 1436 | dbg("%s - usb_alloc_urb failed: usbtouch->irq", __func__); |
| 1585 | "%s - usb_alloc_urb failed: usbtouch->irq\n", __func__); | ||
| 1586 | goto out_free_buffers; | 1437 | goto out_free_buffers; |
| 1587 | } | 1438 | } |
| 1588 | 1439 | ||
| @@ -1644,9 +1495,7 @@ static int usbtouch_probe(struct usb_interface *intf, | |||
| 1644 | if (type->alloc) { | 1495 | if (type->alloc) { |
| 1645 | err = type->alloc(usbtouch); | 1496 | err = type->alloc(usbtouch); |
| 1646 | if (err) { | 1497 | if (err) { |
| 1647 | dev_dbg(&intf->dev, | 1498 | dbg("%s - type->alloc() failed, err: %d", __func__, err); |
| 1648 | "%s - type->alloc() failed, err: %d\n", | ||
| 1649 | __func__, err); | ||
| 1650 | goto out_free_urb; | 1499 | goto out_free_urb; |
| 1651 | } | 1500 | } |
| 1652 | } | 1501 | } |
| @@ -1655,18 +1504,14 @@ static int usbtouch_probe(struct usb_interface *intf, | |||
| 1655 | if (type->init) { | 1504 | if (type->init) { |
| 1656 | err = type->init(usbtouch); | 1505 | err = type->init(usbtouch); |
| 1657 | if (err) { | 1506 | if (err) { |
| 1658 | dev_dbg(&intf->dev, | 1507 | dbg("%s - type->init() failed, err: %d", __func__, err); |
| 1659 | "%s - type->init() failed, err: %d\n", | ||
| 1660 | __func__, err); | ||
| 1661 | goto out_do_exit; | 1508 | goto out_do_exit; |
| 1662 | } | 1509 | } |
| 1663 | } | 1510 | } |
| 1664 | 1511 | ||
| 1665 | err = input_register_device(usbtouch->input); | 1512 | err = input_register_device(usbtouch->input); |
| 1666 | if (err) { | 1513 | if (err) { |
| 1667 | dev_dbg(&intf->dev, | 1514 | dbg("%s - input_register_device failed, err: %d", __func__, err); |
| 1668 | "%s - input_register_device failed, err: %d\n", | ||
| 1669 | __func__, err); | ||
| 1670 | goto out_do_exit; | 1515 | goto out_do_exit; |
| 1671 | } | 1516 | } |
| 1672 | 1517 | ||
| @@ -1678,9 +1523,8 @@ static int usbtouch_probe(struct usb_interface *intf, | |||
| 1678 | err = usb_submit_urb(usbtouch->irq, GFP_KERNEL); | 1523 | err = usb_submit_urb(usbtouch->irq, GFP_KERNEL); |
| 1679 | if (err) { | 1524 | if (err) { |
| 1680 | usb_autopm_put_interface(intf); | 1525 | usb_autopm_put_interface(intf); |
| 1681 | dev_err(&intf->dev, | 1526 | err("%s - usb_submit_urb failed with result: %d", |
| 1682 | "%s - usb_submit_urb failed with result: %d\n", | 1527 | __func__, err); |
| 1683 | __func__, err); | ||
| 1684 | goto out_unregister_input; | 1528 | goto out_unregister_input; |
| 1685 | } | 1529 | } |
| 1686 | } | 1530 | } |
| @@ -1707,12 +1551,12 @@ static void usbtouch_disconnect(struct usb_interface *intf) | |||
| 1707 | { | 1551 | { |
| 1708 | struct usbtouch_usb *usbtouch = usb_get_intfdata(intf); | 1552 | struct usbtouch_usb *usbtouch = usb_get_intfdata(intf); |
| 1709 | 1553 | ||
| 1554 | dbg("%s - called", __func__); | ||
| 1555 | |||
| 1710 | if (!usbtouch) | 1556 | if (!usbtouch) |
| 1711 | return; | 1557 | return; |
| 1712 | 1558 | ||
| 1713 | dev_dbg(&intf->dev, | 1559 | dbg("%s - usbtouch is initialized, cleaning up", __func__); |
| 1714 | "%s - usbtouch is initialized, cleaning up\n", __func__); | ||
| 1715 | |||
| 1716 | usb_set_intfdata(intf, NULL); | 1560 | usb_set_intfdata(intf, NULL); |
| 1717 | /* this will stop IO via close */ | 1561 | /* this will stop IO via close */ |
| 1718 | input_unregister_device(usbtouch->input); | 1562 | input_unregister_device(usbtouch->input); |
| @@ -1736,7 +1580,18 @@ static struct usb_driver usbtouch_driver = { | |||
| 1736 | .supports_autosuspend = 1, | 1580 | .supports_autosuspend = 1, |
| 1737 | }; | 1581 | }; |
| 1738 | 1582 | ||
| 1739 | module_usb_driver(usbtouch_driver); | 1583 | static int __init usbtouch_init(void) |
| 1584 | { | ||
| 1585 | return usb_register(&usbtouch_driver); | ||
| 1586 | } | ||
| 1587 | |||
| 1588 | static void __exit usbtouch_cleanup(void) | ||
| 1589 | { | ||
| 1590 | usb_deregister(&usbtouch_driver); | ||
| 1591 | } | ||
| 1592 | |||
| 1593 | module_init(usbtouch_init); | ||
| 1594 | module_exit(usbtouch_cleanup); | ||
| 1740 | 1595 | ||
| 1741 | MODULE_AUTHOR(DRIVER_AUTHOR); | 1596 | MODULE_AUTHOR(DRIVER_AUTHOR); |
| 1742 | MODULE_DESCRIPTION(DRIVER_DESC); | 1597 | MODULE_DESCRIPTION(DRIVER_DESC); |
diff --git a/drivers/input/touchscreen/w90p910_ts.c b/drivers/input/touchscreen/w90p910_ts.c index d2ef8f05c66..7a45d68c351 100644 --- a/drivers/input/touchscreen/w90p910_ts.c +++ b/drivers/input/touchscreen/w90p910_ts.c | |||
| @@ -215,7 +215,7 @@ static void w90p910_close(struct input_dev *dev) | |||
| 215 | clk_disable(w90p910_ts->clk); | 215 | clk_disable(w90p910_ts->clk); |
| 216 | } | 216 | } |
| 217 | 217 | ||
| 218 | static int w90x900ts_probe(struct platform_device *pdev) | 218 | static int __devinit w90x900ts_probe(struct platform_device *pdev) |
| 219 | { | 219 | { |
| 220 | struct w90p910_ts *w90p910_ts; | 220 | struct w90p910_ts *w90p910_ts; |
| 221 | struct input_dev *input_dev; | 221 | struct input_dev *input_dev; |
| @@ -279,7 +279,7 @@ static int w90x900ts_probe(struct platform_device *pdev) | |||
| 279 | 279 | ||
| 280 | w90p910_ts->irq_num = platform_get_irq(pdev, 0); | 280 | w90p910_ts->irq_num = platform_get_irq(pdev, 0); |
| 281 | if (request_irq(w90p910_ts->irq_num, w90p910_ts_interrupt, | 281 | if (request_irq(w90p910_ts->irq_num, w90p910_ts_interrupt, |
| 282 | 0, "w90p910ts", w90p910_ts)) { | 282 | IRQF_DISABLED, "w90p910ts", w90p910_ts)) { |
| 283 | err = -EBUSY; | 283 | err = -EBUSY; |
| 284 | goto fail4; | 284 | goto fail4; |
| 285 | } | 285 | } |
| @@ -301,7 +301,7 @@ fail1: input_free_device(input_dev); | |||
| 301 | return err; | 301 | return err; |
| 302 | } | 302 | } |
| 303 | 303 | ||
| 304 | static int w90x900ts_remove(struct platform_device *pdev) | 304 | static int __devexit w90x900ts_remove(struct platform_device *pdev) |
| 305 | { | 305 | { |
| 306 | struct w90p910_ts *w90p910_ts = platform_get_drvdata(pdev); | 306 | struct w90p910_ts *w90p910_ts = platform_get_drvdata(pdev); |
| 307 | struct resource *res; | 307 | struct resource *res; |
| @@ -325,13 +325,25 @@ static int w90x900ts_remove(struct platform_device *pdev) | |||
| 325 | 325 | ||
| 326 | static struct platform_driver w90x900ts_driver = { | 326 | static struct platform_driver w90x900ts_driver = { |
| 327 | .probe = w90x900ts_probe, | 327 | .probe = w90x900ts_probe, |
| 328 | .remove = w90x900ts_remove, | 328 | .remove = __devexit_p(w90x900ts_remove), |
| 329 | .driver = { | 329 | .driver = { |
| 330 | .name = "nuc900-ts", | 330 | .name = "nuc900-ts", |
| 331 | .owner = THIS_MODULE, | 331 | .owner = THIS_MODULE, |
| 332 | }, | 332 | }, |
| 333 | }; | 333 | }; |
| 334 | module_platform_driver(w90x900ts_driver); | 334 | |
| 335 | static int __init w90x900ts_init(void) | ||
| 336 | { | ||
| 337 | return platform_driver_register(&w90x900ts_driver); | ||
| 338 | } | ||
| 339 | |||
| 340 | static void __exit w90x900ts_exit(void) | ||
| 341 | { | ||
| 342 | platform_driver_unregister(&w90x900ts_driver); | ||
| 343 | } | ||
| 344 | |||
| 345 | module_init(w90x900ts_init); | ||
| 346 | module_exit(w90x900ts_exit); | ||
| 335 | 347 | ||
| 336 | MODULE_AUTHOR("Wan ZongShun <mcuos.com@gmail.com>"); | 348 | MODULE_AUTHOR("Wan ZongShun <mcuos.com@gmail.com>"); |
| 337 | MODULE_DESCRIPTION("w90p910 touch screen driver!"); | 349 | MODULE_DESCRIPTION("w90p910 touch screen driver!"); |
diff --git a/drivers/input/touchscreen/wacom_i2c.c b/drivers/input/touchscreen/wacom_i2c.c deleted file mode 100644 index bf0d07620ba..00000000000 --- a/drivers/input/touchscreen/wacom_i2c.c +++ /dev/null | |||
| @@ -1,282 +0,0 @@ | |||
| 1 | /* | ||
| 2 | * Wacom Penabled Driver for I2C | ||
| 3 | * | ||
| 4 | * Copyright (c) 2011 Tatsunosuke Tobita, Wacom. | ||
| 5 | * <tobita.tatsunosuke@wacom.co.jp> | ||
| 6 | * | ||
| 7 | * This program is free software; you can redistribute it | ||
| 8 | * and/or modify it under the terms of the GNU General | ||
| 9 | * Public License as published by the Free Software | ||
| 10 | * Foundation; either version of 2 of the License, | ||
| 11 | * or (at your option) any later version. | ||
| 12 | */ | ||
| 13 | |||
| 14 | #include <linux/module.h> | ||
| 15 | #include <linux/input.h> | ||
| 16 | #include <linux/i2c.h> | ||
| 17 | #include <linux/slab.h> | ||
| 18 | #include <linux/irq.h> | ||
| 19 | #include <linux/interrupt.h> | ||
| 20 | #include <linux/gpio.h> | ||
| 21 | #include <asm/unaligned.h> | ||
| 22 | |||
| 23 | #define WACOM_CMD_QUERY0 0x04 | ||
| 24 | #define WACOM_CMD_QUERY1 0x00 | ||
| 25 | #define WACOM_CMD_QUERY2 0x33 | ||
| 26 | #define WACOM_CMD_QUERY3 0x02 | ||
| 27 | #define WACOM_CMD_THROW0 0x05 | ||
| 28 | #define WACOM_CMD_THROW1 0x00 | ||
| 29 | #define WACOM_QUERY_SIZE 19 | ||
| 30 | #define WACOM_RETRY_CNT 100 | ||
| 31 | |||
| 32 | struct wacom_features { | ||
| 33 | int x_max; | ||
| 34 | int y_max; | ||
| 35 | int pressure_max; | ||
| 36 | char fw_version; | ||
| 37 | }; | ||
| 38 | |||
| 39 | struct wacom_i2c { | ||
| 40 | struct i2c_client *client; | ||
| 41 | struct input_dev *input; | ||
| 42 | u8 data[WACOM_QUERY_SIZE]; | ||
| 43 | }; | ||
| 44 | |||
| 45 | static int wacom_query_device(struct i2c_client *client, | ||
| 46 | struct wacom_features *features) | ||
| 47 | { | ||
| 48 | int ret; | ||
| 49 | u8 cmd1[] = { WACOM_CMD_QUERY0, WACOM_CMD_QUERY1, | ||
| 50 | WACOM_CMD_QUERY2, WACOM_CMD_QUERY3 }; | ||
| 51 | u8 cmd2[] = { WACOM_CMD_THROW0, WACOM_CMD_THROW1 }; | ||
| 52 | u8 data[WACOM_QUERY_SIZE]; | ||
| 53 | struct i2c_msg msgs[] = { | ||
| 54 | { | ||
| 55 | .addr = client->addr, | ||
| 56 | .flags = 0, | ||
| 57 | .len = sizeof(cmd1), | ||
| 58 | .buf = cmd1, | ||
| 59 | }, | ||
| 60 | { | ||
| 61 | .addr = client->addr, | ||
| 62 | .flags = 0, | ||
| 63 | .len = sizeof(cmd2), | ||
| 64 | .buf = cmd2, | ||
| 65 | }, | ||
| 66 | { | ||
| 67 | .addr = client->addr, | ||
| 68 | .flags = I2C_M_RD, | ||
| 69 | .len = sizeof(data), | ||
| 70 | .buf = data, | ||
| 71 | }, | ||
| 72 | }; | ||
| 73 | |||
| 74 | ret = i2c_transfer(client->adapter, msgs, ARRAY_SIZE(msgs)); | ||
| 75 | if (ret < 0) | ||
| 76 | return ret; | ||
| 77 | if (ret != ARRAY_SIZE(msgs)) | ||
| 78 | return -EIO; | ||
| 79 | |||
| 80 | features->x_max = get_unaligned_le16(&data[3]); | ||
| 81 | features->y_max = get_unaligned_le16(&data[5]); | ||
| 82 | features->pressure_max = get_unaligned_le16(&data[11]); | ||
| 83 | features->fw_version = get_unaligned_le16(&data[13]); | ||
| 84 | |||
| 85 | dev_dbg(&client->dev, | ||
| 86 | "x_max:%d, y_max:%d, pressure:%d, fw:%d\n", | ||
| 87 | features->x_max, features->y_max, | ||
| 88 | features->pressure_max, features->fw_version); | ||
| 89 | |||
| 90 | return 0; | ||
| 91 | } | ||
| 92 | |||
| 93 | static irqreturn_t wacom_i2c_irq(int irq, void *dev_id) | ||
| 94 | { | ||
| 95 | struct wacom_i2c *wac_i2c = dev_id; | ||
| 96 | struct input_dev *input = wac_i2c->input; | ||
| 97 | u8 *data = wac_i2c->data; | ||
| 98 | unsigned int x, y, pressure; | ||
| 99 | unsigned char tsw, f1, f2, ers; | ||
| 100 | int error; | ||
| 101 | |||
| 102 | error = i2c_master_recv(wac_i2c->client, | ||
| 103 | wac_i2c->data, sizeof(wac_i2c->data)); | ||
| 104 | if (error < 0) | ||
| 105 | goto out; | ||
| 106 | |||
| 107 | tsw = data[3] & 0x01; | ||
| 108 | ers = data[3] & 0x04; | ||
| 109 | f1 = data[3] & 0x02; | ||
| 110 | f2 = data[3] & 0x10; | ||
| 111 | x = le16_to_cpup((__le16 *)&data[4]); | ||
| 112 | y = le16_to_cpup((__le16 *)&data[6]); | ||
| 113 | pressure = le16_to_cpup((__le16 *)&data[8]); | ||
| 114 | |||
| 115 | input_report_key(input, BTN_TOUCH, tsw || ers); | ||
| 116 | input_report_key(input, BTN_TOOL_PEN, tsw); | ||
| 117 | input_report_key(input, BTN_TOOL_RUBBER, ers); | ||
| 118 | input_report_key(input, BTN_STYLUS, f1); | ||
| 119 | input_report_key(input, BTN_STYLUS2, f2); | ||
| 120 | input_report_abs(input, ABS_X, x); | ||
| 121 | input_report_abs(input, ABS_Y, y); | ||
| 122 | input_report_abs(input, ABS_PRESSURE, pressure); | ||
| 123 | input_sync(input); | ||
| 124 | |||
| 125 | out: | ||
| 126 | return IRQ_HANDLED; | ||
| 127 | } | ||
| 128 | |||
| 129 | static int wacom_i2c_open(struct input_dev *dev) | ||
| 130 | { | ||
| 131 | struct wacom_i2c *wac_i2c = input_get_drvdata(dev); | ||
| 132 | struct i2c_client *client = wac_i2c->client; | ||
| 133 | |||
| 134 | enable_irq(client->irq); | ||
| 135 | |||
| 136 | return 0; | ||
| 137 | } | ||
| 138 | |||
| 139 | static void wacom_i2c_close(struct input_dev *dev) | ||
| 140 | { | ||
| 141 | struct wacom_i2c *wac_i2c = input_get_drvdata(dev); | ||
| 142 | struct i2c_client *client = wac_i2c->client; | ||
| 143 | |||
| 144 | disable_irq(client->irq); | ||
| 145 | } | ||
| 146 | |||
| 147 | static int wacom_i2c_probe(struct i2c_client *client, | ||
| 148 | const struct i2c_device_id *id) | ||
| 149 | { | ||
| 150 | struct wacom_i2c *wac_i2c; | ||
| 151 | struct input_dev *input; | ||
| 152 | struct wacom_features features = { 0 }; | ||
| 153 | int error; | ||
| 154 | |||
| 155 | if (!i2c_check_functionality(client->adapter, I2C_FUNC_I2C)) { | ||
| 156 | dev_err(&client->dev, "i2c_check_functionality error\n"); | ||
| 157 | return -EIO; | ||
| 158 | } | ||
| 159 | |||
| 160 | error = wacom_query_device(client, &features); | ||
| 161 | if (error) | ||
| 162 | return error; | ||
| 163 | |||
| 164 | wac_i2c = kzalloc(sizeof(*wac_i2c), GFP_KERNEL); | ||
| 165 | input = input_allocate_device(); | ||
| 166 | if (!wac_i2c || !input) { | ||
| 167 | error = -ENOMEM; | ||
| 168 | goto err_free_mem; | ||
| 169 | } | ||
| 170 | |||
| 171 | wac_i2c->client = client; | ||
| 172 | wac_i2c->input = input; | ||
| 173 | |||
| 174 | input->name = "Wacom I2C Digitizer"; | ||
| 175 | input->id.bustype = BUS_I2C; | ||
| 176 | input->id.vendor = 0x56a; | ||
| 177 | input->id.version = features.fw_version; | ||
| 178 | input->dev.parent = &client->dev; | ||
| 179 | input->open = wacom_i2c_open; | ||
| 180 | input->close = wacom_i2c_close; | ||
| 181 | |||
| 182 | input->evbit[0] |= BIT_MASK(EV_KEY) | BIT_MASK(EV_ABS); | ||
| 183 | |||
| 184 | __set_bit(BTN_TOOL_PEN, input->keybit); | ||
| 185 | __set_bit(BTN_TOOL_RUBBER, input->keybit); | ||
| 186 | __set_bit(BTN_STYLUS, input->keybit); | ||
| 187 | __set_bit(BTN_STYLUS2, input->keybit); | ||
| 188 | __set_bit(BTN_TOUCH, input->keybit); | ||
| 189 | |||
| 190 | input_set_abs_params(input, ABS_X, 0, features.x_max, 0, 0); | ||
| 191 | input_set_abs_params(input, ABS_Y, 0, features.y_max, 0, 0); | ||
| 192 | input_set_abs_params(input, ABS_PRESSURE, | ||
| 193 | 0, features.pressure_max, 0, 0); | ||
| 194 | |||
| 195 | input_set_drvdata(input, wac_i2c); | ||
| 196 | |||
| 197 | error = request_threaded_irq(client->irq, NULL, wacom_i2c_irq, | ||
| 198 | IRQF_TRIGGER_LOW | IRQF_ONESHOT, | ||
| 199 | "wacom_i2c", wac_i2c); | ||
| 200 | if (error) { | ||
| 201 | dev_err(&client->dev, | ||
| 202 | "Failed to enable IRQ, error: %d\n", error); | ||
| 203 | goto err_free_mem; | ||
| 204 | } | ||
| 205 | |||
| 206 | /* Disable the IRQ, we'll enable it in wac_i2c_open() */ | ||
| 207 | disable_irq(client->irq); | ||
| 208 | |||
| 209 | error = input_register_device(wac_i2c->input); | ||
| 210 | if (error) { | ||
| 211 | dev_err(&client->dev, | ||
| 212 | "Failed to register input device, error: %d\n", error); | ||
| 213 | goto err_free_irq; | ||
| 214 | } | ||
| 215 | |||
| 216 | i2c_set_clientdata(client, wac_i2c); | ||
| 217 | return 0; | ||
| 218 | |||
| 219 | err_free_irq: | ||
| 220 | free_irq(client->irq, wac_i2c); | ||
| 221 | err_free_mem: | ||
| 222 | input_free_device(input); | ||
| 223 | kfree(wac_i2c); | ||
| 224 | |||
| 225 | return error; | ||
| 226 | } | ||
| 227 | |||
| 228 | static int wacom_i2c_remove(struct i2c_client *client) | ||
| 229 | { | ||
| 230 | struct wacom_i2c *wac_i2c = i2c_get_clientdata(client); | ||
| 231 | |||
| 232 | free_irq(client->irq, wac_i2c); | ||
| 233 | input_unregister_device(wac_i2c->input); | ||
| 234 | kfree(wac_i2c); | ||
| 235 | |||
| 236 | return 0; | ||
| 237 | } | ||
| 238 | |||
| 239 | #ifdef CONFIG_PM_SLEEP | ||
| 240 | static int wacom_i2c_suspend(struct device *dev) | ||
| 241 | { | ||
| 242 | struct i2c_client *client = to_i2c_client(dev); | ||
| 243 | |||
| 244 | disable_irq(client->irq); | ||
| 245 | |||
| 246 | return 0; | ||
| 247 | } | ||
| 248 | |||
| 249 | static int wacom_i2c_resume(struct device *dev) | ||
| 250 | { | ||
| 251 | struct i2c_client *client = to_i2c_client(dev); | ||
| 252 | |||
| 253 | enable_irq(client->irq); | ||
| 254 | |||
| 255 | return 0; | ||
| 256 | } | ||
| 257 | #endif | ||
| 258 | |||
| 259 | static SIMPLE_DEV_PM_OPS(wacom_i2c_pm, wacom_i2c_suspend, wacom_i2c_resume); | ||
| 260 | |||
| 261 | static const struct i2c_device_id wacom_i2c_id[] = { | ||
| 262 | { "WAC_I2C_EMR", 0 }, | ||
| 263 | { }, | ||
| 264 | }; | ||
| 265 | MODULE_DEVICE_TABLE(i2c, wacom_i2c_id); | ||
| 266 | |||
| 267 | static struct i2c_driver wacom_i2c_driver = { | ||
| 268 | .driver = { | ||
| 269 | .name = "wacom_i2c", | ||
| 270 | .owner = THIS_MODULE, | ||
| 271 | .pm = &wacom_i2c_pm, | ||
| 272 | }, | ||
| 273 | |||
| 274 | .probe = wacom_i2c_probe, | ||
| 275 | .remove = wacom_i2c_remove, | ||
| 276 | .id_table = wacom_i2c_id, | ||
| 277 | }; | ||
| 278 | module_i2c_driver(wacom_i2c_driver); | ||
| 279 | |||
| 280 | MODULE_AUTHOR("Tatsunosuke Tobita <tobita.tatsunosuke@wacom.co.jp>"); | ||
| 281 | MODULE_DESCRIPTION("WACOM EMR I2C Driver"); | ||
| 282 | MODULE_LICENSE("GPL"); | ||
diff --git a/drivers/input/touchscreen/wacom_w8001.c b/drivers/input/touchscreen/wacom_w8001.c index 9a83be6b658..9941d39df43 100644 --- a/drivers/input/touchscreen/wacom_w8001.c +++ b/drivers/input/touchscreen/wacom_w8001.c | |||
| @@ -367,20 +367,6 @@ static int w8001_command(struct w8001 *w8001, unsigned char command, | |||
| 367 | return rc; | 367 | return rc; |
| 368 | } | 368 | } |
| 369 | 369 | ||
| 370 | static int w8001_open(struct input_dev *dev) | ||
| 371 | { | ||
| 372 | struct w8001 *w8001 = input_get_drvdata(dev); | ||
| 373 | |||
| 374 | return w8001_command(w8001, W8001_CMD_START, false); | ||
| 375 | } | ||
| 376 | |||
| 377 | static void w8001_close(struct input_dev *dev) | ||
| 378 | { | ||
| 379 | struct w8001 *w8001 = input_get_drvdata(dev); | ||
| 380 | |||
| 381 | w8001_command(w8001, W8001_CMD_STOP, false); | ||
| 382 | } | ||
| 383 | |||
| 384 | static int w8001_setup(struct w8001 *w8001) | 370 | static int w8001_setup(struct w8001 *w8001) |
| 385 | { | 371 | { |
| 386 | struct input_dev *dev = w8001->dev; | 372 | struct input_dev *dev = w8001->dev; |
| @@ -471,7 +457,7 @@ static int w8001_setup(struct w8001 *w8001) | |||
| 471 | case 5: | 457 | case 5: |
| 472 | w8001->pktlen = W8001_PKTLEN_TOUCH2FG; | 458 | w8001->pktlen = W8001_PKTLEN_TOUCH2FG; |
| 473 | 459 | ||
| 474 | input_mt_init_slots(dev, 2, 0); | 460 | input_mt_init_slots(dev, 2); |
| 475 | input_set_abs_params(dev, ABS_MT_POSITION_X, | 461 | input_set_abs_params(dev, ABS_MT_POSITION_X, |
| 476 | 0, touch.x, 0, 0); | 462 | 0, touch.x, 0, 0); |
| 477 | input_set_abs_params(dev, ABS_MT_POSITION_Y, | 463 | input_set_abs_params(dev, ABS_MT_POSITION_Y, |
| @@ -490,7 +476,7 @@ static int w8001_setup(struct w8001 *w8001) | |||
| 490 | 476 | ||
| 491 | strlcat(w8001->name, " Touchscreen", sizeof(w8001->name)); | 477 | strlcat(w8001->name, " Touchscreen", sizeof(w8001->name)); |
| 492 | 478 | ||
| 493 | return 0; | 479 | return w8001_command(w8001, W8001_CMD_START, false); |
| 494 | } | 480 | } |
| 495 | 481 | ||
| 496 | /* | 482 | /* |
| @@ -501,12 +487,12 @@ static void w8001_disconnect(struct serio *serio) | |||
| 501 | { | 487 | { |
| 502 | struct w8001 *w8001 = serio_get_drvdata(serio); | 488 | struct w8001 *w8001 = serio_get_drvdata(serio); |
| 503 | 489 | ||
| 504 | serio_close(serio); | 490 | input_get_device(w8001->dev); |
| 505 | |||
| 506 | input_unregister_device(w8001->dev); | 491 | input_unregister_device(w8001->dev); |
| 507 | kfree(w8001); | 492 | serio_close(serio); |
| 508 | |||
| 509 | serio_set_drvdata(serio, NULL); | 493 | serio_set_drvdata(serio, NULL); |
| 494 | input_put_device(w8001->dev); | ||
| 495 | kfree(w8001); | ||
| 510 | } | 496 | } |
| 511 | 497 | ||
| 512 | /* | 498 | /* |
| @@ -550,11 +536,6 @@ static int w8001_connect(struct serio *serio, struct serio_driver *drv) | |||
| 550 | input_dev->id.version = 0x0100; | 536 | input_dev->id.version = 0x0100; |
| 551 | input_dev->dev.parent = &serio->dev; | 537 | input_dev->dev.parent = &serio->dev; |
| 552 | 538 | ||
| 553 | input_dev->open = w8001_open; | ||
| 554 | input_dev->close = w8001_close; | ||
| 555 | |||
| 556 | input_set_drvdata(input_dev, w8001); | ||
| 557 | |||
| 558 | err = input_register_device(w8001->dev); | 539 | err = input_register_device(w8001->dev); |
| 559 | if (err) | 540 | if (err) |
| 560 | goto fail3; | 541 | goto fail3; |
| @@ -594,4 +575,15 @@ static struct serio_driver w8001_drv = { | |||
| 594 | .disconnect = w8001_disconnect, | 575 | .disconnect = w8001_disconnect, |
| 595 | }; | 576 | }; |
| 596 | 577 | ||
| 597 | module_serio_driver(w8001_drv); | 578 | static int __init w8001_init(void) |
| 579 | { | ||
| 580 | return serio_register_driver(&w8001_drv); | ||
| 581 | } | ||
| 582 | |||
| 583 | static void __exit w8001_exit(void) | ||
| 584 | { | ||
| 585 | serio_unregister_driver(&w8001_drv); | ||
| 586 | } | ||
| 587 | |||
| 588 | module_init(w8001_init); | ||
| 589 | module_exit(w8001_exit); | ||
diff --git a/drivers/input/touchscreen/wm831x-ts.c b/drivers/input/touchscreen/wm831x-ts.c index f88fab56178..9175d49d254 100644 --- a/drivers/input/touchscreen/wm831x-ts.c +++ b/drivers/input/touchscreen/wm831x-ts.c | |||
| @@ -221,7 +221,7 @@ static void wm831x_ts_input_close(struct input_dev *idev) | |||
| 221 | synchronize_irq(wm831x_ts->pd_irq); | 221 | synchronize_irq(wm831x_ts->pd_irq); |
| 222 | 222 | ||
| 223 | /* Make sure the IRQ completion work is quiesced */ | 223 | /* Make sure the IRQ completion work is quiesced */ |
| 224 | flush_work(&wm831x_ts->pd_data_work); | 224 | flush_work_sync(&wm831x_ts->pd_data_work); |
| 225 | 225 | ||
| 226 | /* If we ended up with the pen down then make sure we revert back | 226 | /* If we ended up with the pen down then make sure we revert back |
| 227 | * to pen detection state for the next time we start up. | 227 | * to pen detection state for the next time we start up. |
| @@ -233,7 +233,7 @@ static void wm831x_ts_input_close(struct input_dev *idev) | |||
| 233 | } | 233 | } |
| 234 | } | 234 | } |
| 235 | 235 | ||
| 236 | static int wm831x_ts_probe(struct platform_device *pdev) | 236 | static __devinit int wm831x_ts_probe(struct platform_device *pdev) |
| 237 | { | 237 | { |
| 238 | struct wm831x_ts *wm831x_ts; | 238 | struct wm831x_ts *wm831x_ts; |
| 239 | struct wm831x *wm831x = dev_get_drvdata(pdev->dev.parent); | 239 | struct wm831x *wm831x = dev_get_drvdata(pdev->dev.parent); |
| @@ -245,8 +245,7 @@ static int wm831x_ts_probe(struct platform_device *pdev) | |||
| 245 | if (core_pdata) | 245 | if (core_pdata) |
| 246 | pdata = core_pdata->touch; | 246 | pdata = core_pdata->touch; |
| 247 | 247 | ||
| 248 | wm831x_ts = devm_kzalloc(&pdev->dev, sizeof(struct wm831x_ts), | 248 | wm831x_ts = kzalloc(sizeof(struct wm831x_ts), GFP_KERNEL); |
| 249 | GFP_KERNEL); | ||
| 250 | input_dev = input_allocate_device(); | 249 | input_dev = input_allocate_device(); |
| 251 | if (!wm831x_ts || !input_dev) { | 250 | if (!wm831x_ts || !input_dev) { |
| 252 | error = -ENOMEM; | 251 | error = -ENOMEM; |
| @@ -261,16 +260,15 @@ static int wm831x_ts_probe(struct platform_device *pdev) | |||
| 261 | * If we have a direct IRQ use it, otherwise use the interrupt | 260 | * If we have a direct IRQ use it, otherwise use the interrupt |
| 262 | * from the WM831x IRQ controller. | 261 | * from the WM831x IRQ controller. |
| 263 | */ | 262 | */ |
| 264 | wm831x_ts->data_irq = wm831x_irq(wm831x, | ||
| 265 | platform_get_irq_byname(pdev, | ||
| 266 | "TCHDATA")); | ||
| 267 | if (pdata && pdata->data_irq) | 263 | if (pdata && pdata->data_irq) |
| 268 | wm831x_ts->data_irq = pdata->data_irq; | 264 | wm831x_ts->data_irq = pdata->data_irq; |
| 265 | else | ||
| 266 | wm831x_ts->data_irq = platform_get_irq_byname(pdev, "TCHDATA"); | ||
| 269 | 267 | ||
| 270 | wm831x_ts->pd_irq = wm831x_irq(wm831x, | ||
| 271 | platform_get_irq_byname(pdev, "TCHPD")); | ||
| 272 | if (pdata && pdata->pd_irq) | 268 | if (pdata && pdata->pd_irq) |
| 273 | wm831x_ts->pd_irq = pdata->pd_irq; | 269 | wm831x_ts->pd_irq = pdata->pd_irq; |
| 270 | else | ||
| 271 | wm831x_ts->pd_irq = platform_get_irq_byname(pdev, "TCHPD"); | ||
| 274 | 272 | ||
| 275 | if (pdata) | 273 | if (pdata) |
| 276 | wm831x_ts->pressure = pdata->pressure; | 274 | wm831x_ts->pressure = pdata->pressure; |
| @@ -377,18 +375,21 @@ err_data_irq: | |||
| 377 | free_irq(wm831x_ts->data_irq, wm831x_ts); | 375 | free_irq(wm831x_ts->data_irq, wm831x_ts); |
| 378 | err_alloc: | 376 | err_alloc: |
| 379 | input_free_device(input_dev); | 377 | input_free_device(input_dev); |
| 378 | kfree(wm831x_ts); | ||
| 380 | 379 | ||
| 381 | return error; | 380 | return error; |
| 382 | } | 381 | } |
| 383 | 382 | ||
| 384 | static int wm831x_ts_remove(struct platform_device *pdev) | 383 | static __devexit int wm831x_ts_remove(struct platform_device *pdev) |
| 385 | { | 384 | { |
| 386 | struct wm831x_ts *wm831x_ts = platform_get_drvdata(pdev); | 385 | struct wm831x_ts *wm831x_ts = platform_get_drvdata(pdev); |
| 387 | 386 | ||
| 388 | free_irq(wm831x_ts->pd_irq, wm831x_ts); | 387 | free_irq(wm831x_ts->pd_irq, wm831x_ts); |
| 389 | free_irq(wm831x_ts->data_irq, wm831x_ts); | 388 | free_irq(wm831x_ts->data_irq, wm831x_ts); |
| 390 | input_unregister_device(wm831x_ts->input_dev); | 389 | input_unregister_device(wm831x_ts->input_dev); |
| 390 | kfree(wm831x_ts); | ||
| 391 | 391 | ||
| 392 | platform_set_drvdata(pdev, NULL); | ||
| 392 | return 0; | 393 | return 0; |
| 393 | } | 394 | } |
| 394 | 395 | ||
| @@ -398,9 +399,20 @@ static struct platform_driver wm831x_ts_driver = { | |||
| 398 | .owner = THIS_MODULE, | 399 | .owner = THIS_MODULE, |
| 399 | }, | 400 | }, |
| 400 | .probe = wm831x_ts_probe, | 401 | .probe = wm831x_ts_probe, |
| 401 | .remove = wm831x_ts_remove, | 402 | .remove = __devexit_p(wm831x_ts_remove), |
| 402 | }; | 403 | }; |
| 403 | module_platform_driver(wm831x_ts_driver); | 404 | |
| 405 | static int __init wm831x_ts_init(void) | ||
| 406 | { | ||
| 407 | return platform_driver_register(&wm831x_ts_driver); | ||
| 408 | } | ||
| 409 | module_init(wm831x_ts_init); | ||
| 410 | |||
| 411 | static void __exit wm831x_ts_exit(void) | ||
| 412 | { | ||
| 413 | platform_driver_unregister(&wm831x_ts_driver); | ||
| 414 | } | ||
| 415 | module_exit(wm831x_ts_exit); | ||
| 404 | 416 | ||
| 405 | /* Module information */ | 417 | /* Module information */ |
| 406 | MODULE_AUTHOR("Mark Brown <broonie@opensource.wolfsonmicro.com>"); | 418 | MODULE_AUTHOR("Mark Brown <broonie@opensource.wolfsonmicro.com>"); |
diff --git a/drivers/input/touchscreen/zylonite-wm97xx.c b/drivers/input/touchscreen/zylonite-wm97xx.c index bf0869a7a78..f6328c0cded 100644 --- a/drivers/input/touchscreen/zylonite-wm97xx.c +++ b/drivers/input/touchscreen/zylonite-wm97xx.c | |||
| @@ -22,7 +22,6 @@ | |||
| 22 | #include <linux/kernel.h> | 22 | #include <linux/kernel.h> |
| 23 | #include <linux/init.h> | 23 | #include <linux/init.h> |
| 24 | #include <linux/delay.h> | 24 | #include <linux/delay.h> |
| 25 | #include <linux/gpio.h> | ||
| 26 | #include <linux/irq.h> | 25 | #include <linux/irq.h> |
| 27 | #include <linux/interrupt.h> | 26 | #include <linux/interrupt.h> |
| 28 | #include <linux/io.h> | 27 | #include <linux/io.h> |
| @@ -193,8 +192,8 @@ static int zylonite_wm97xx_probe(struct platform_device *pdev) | |||
| 193 | else | 192 | else |
| 194 | gpio_touch_irq = mfp_to_gpio(MFP_PIN_GPIO26); | 193 | gpio_touch_irq = mfp_to_gpio(MFP_PIN_GPIO26); |
| 195 | 194 | ||
| 196 | wm->pen_irq = gpio_to_irq(gpio_touch_irq); | 195 | wm->pen_irq = IRQ_GPIO(gpio_touch_irq); |
| 197 | irq_set_irq_type(wm->pen_irq, IRQ_TYPE_EDGE_BOTH); | 196 | irq_set_irq_type(IRQ_GPIO(gpio_touch_irq), IRQ_TYPE_EDGE_BOTH); |
| 198 | 197 | ||
| 199 | wm97xx_config_gpio(wm, WM97XX_GPIO_13, WM97XX_GPIO_IN, | 198 | wm97xx_config_gpio(wm, WM97XX_GPIO_13, WM97XX_GPIO_IN, |
| 200 | WM97XX_GPIO_POL_HIGH, | 199 | WM97XX_GPIO_POL_HIGH, |
| @@ -224,7 +223,19 @@ static struct platform_driver zylonite_wm97xx_driver = { | |||
| 224 | .name = "wm97xx-touch", | 223 | .name = "wm97xx-touch", |
| 225 | }, | 224 | }, |
| 226 | }; | 225 | }; |
| 227 | module_platform_driver(zylonite_wm97xx_driver); | 226 | |
| 227 | static int __init zylonite_wm97xx_init(void) | ||
| 228 | { | ||
| 229 | return platform_driver_register(&zylonite_wm97xx_driver); | ||
| 230 | } | ||
| 231 | |||
| 232 | static void __exit zylonite_wm97xx_exit(void) | ||
| 233 | { | ||
| 234 | platform_driver_unregister(&zylonite_wm97xx_driver); | ||
| 235 | } | ||
| 236 | |||
| 237 | module_init(zylonite_wm97xx_init); | ||
| 238 | module_exit(zylonite_wm97xx_exit); | ||
| 228 | 239 | ||
| 229 | /* Module information */ | 240 | /* Module information */ |
| 230 | MODULE_AUTHOR("Mark Brown <broonie@opensource.wolfsonmicro.com>"); | 241 | MODULE_AUTHOR("Mark Brown <broonie@opensource.wolfsonmicro.com>"); |
