aboutsummaryrefslogtreecommitdiff
path: root/drivers/input/touchscreen/88pm860x-ts.c
diff options
context:
space:
mode:
Diffstat (limited to 'drivers/input/touchscreen/88pm860x-ts.c')
-rw-r--r--drivers/input/touchscreen/88pm860x-ts.c188
1 files changed, 128 insertions, 60 deletions
diff --git a/drivers/input/touchscreen/88pm860x-ts.c b/drivers/input/touchscreen/88pm860x-ts.c
index b3aebc2166b..0d4a9fad4a7 100644
--- a/drivers/input/touchscreen/88pm860x-ts.c
+++ b/drivers/input/touchscreen/88pm860x-ts.c
@@ -10,11 +10,13 @@
*/
#include <linux/kernel.h>
#include <linux/module.h>
+#include <linux/of.h>
#include <linux/platform_device.h>
#include <linux/i2c.h>
#include <linux/input.h>
#include <linux/mfd/88pm860x.h>
#include <linux/slab.h>
+#include <linux/device.h>
#define MEAS_LEN (8)
#define ACCURATE_BIT (12)
@@ -113,14 +115,69 @@ static void pm860x_touch_close(struct input_dev *dev)
pm860x_set_bits(touch->i2c, MEAS_EN3, data, 0);
}
-static int __devinit pm860x_touch_probe(struct platform_device *pdev)
+#ifdef CONFIG_OF
+static int pm860x_touch_dt_init(struct platform_device *pdev,
+ struct pm860x_chip *chip,
+ int *res_x)
+{
+ struct device_node *np = pdev->dev.parent->of_node;
+ struct i2c_client *i2c = (chip->id == CHIP_PM8607) ? chip->client \
+ : chip->companion;
+ int data, n, ret;
+ if (!np)
+ return -ENODEV;
+ np = of_find_node_by_name(np, "touch");
+ if (!np) {
+ dev_err(&pdev->dev, "Can't find touch node\n");
+ return -EINVAL;
+ }
+ /* set GPADC MISC1 register */
+ data = 0;
+ if (!of_property_read_u32(np, "marvell,88pm860x-gpadc-prebias", &n))
+ data |= (n << 1) & PM8607_GPADC_PREBIAS_MASK;
+ if (!of_property_read_u32(np, "marvell,88pm860x-gpadc-slot-cycle", &n))
+ data |= (n << 3) & PM8607_GPADC_SLOT_CYCLE_MASK;
+ if (!of_property_read_u32(np, "marvell,88pm860x-gpadc-off-scale", &n))
+ data |= (n << 5) & PM8607_GPADC_OFF_SCALE_MASK;
+ if (!of_property_read_u32(np, "marvell,88pm860x-gpadc-sw-cal", &n))
+ data |= (n << 7) & PM8607_GPADC_SW_CAL_MASK;
+ if (data) {
+ ret = pm860x_reg_write(i2c, PM8607_GPADC_MISC1, data);
+ if (ret < 0)
+ return -EINVAL;
+ }
+ /* set tsi prebias time */
+ if (!of_property_read_u32(np, "marvell,88pm860x-tsi-prebias", &data)) {
+ ret = pm860x_reg_write(i2c, PM8607_TSI_PREBIAS, data);
+ if (ret < 0)
+ return -EINVAL;
+ }
+ /* set prebias & prechg time of pen detect */
+ data = 0;
+ if (!of_property_read_u32(np, "marvell,88pm860x-pen-prebias", &n))
+ data |= n & PM8607_PD_PREBIAS_MASK;
+ if (!of_property_read_u32(np, "marvell,88pm860x-pen-prechg", &n))
+ data |= n & PM8607_PD_PRECHG_MASK;
+ if (data) {
+ ret = pm860x_reg_write(i2c, PM8607_PD_PREBIAS, data);
+ if (ret < 0)
+ return -EINVAL;
+ }
+ of_property_read_u32(np, "marvell,88pm860x-resistor-X", res_x);
+ return 0;
+}
+#else
+#define pm860x_touch_dt_init(x, y, z) (-1)
+#endif
+
+static int pm860x_touch_probe(struct platform_device *pdev)
{
struct pm860x_chip *chip = dev_get_drvdata(pdev->dev.parent);
- struct pm860x_platform_data *pm860x_pdata = \
- pdev->dev.parent->platform_data;
- struct pm860x_touch_pdata *pdata = NULL;
+ struct pm860x_touch_pdata *pdata = dev_get_platdata(&pdev->dev);
struct pm860x_touch *touch;
- int irq, ret;
+ struct i2c_client *i2c = (chip->id == CHIP_PM8607) ? chip->client \
+ : chip->companion;
+ int irq, ret, res_x = 0, data = 0;
irq = platform_get_irq(pdev, 0);
if (irq < 0) {
@@ -128,27 +185,67 @@ static int __devinit pm860x_touch_probe(struct platform_device *pdev)
return -EINVAL;
}
- if (!pm860x_pdata) {
- dev_err(&pdev->dev, "platform data is missing\n");
- return -EINVAL;
- }
-
- pdata = pm860x_pdata->touch;
- if (!pdata) {
- dev_err(&pdev->dev, "touchscreen data is missing\n");
- return -EINVAL;
+ if (pm860x_touch_dt_init(pdev, chip, &res_x)) {
+ if (pdata) {
+ /* set GPADC MISC1 register */
+ data = 0;
+ data |= (pdata->gpadc_prebias << 1)
+ & PM8607_GPADC_PREBIAS_MASK;
+ data |= (pdata->slot_cycle << 3)
+ & PM8607_GPADC_SLOT_CYCLE_MASK;
+ data |= (pdata->off_scale << 5)
+ & PM8607_GPADC_OFF_SCALE_MASK;
+ data |= (pdata->sw_cal << 7)
+ & PM8607_GPADC_SW_CAL_MASK;
+ if (data) {
+ ret = pm860x_reg_write(i2c,
+ PM8607_GPADC_MISC1, data);
+ if (ret < 0)
+ return -EINVAL;
+ }
+ /* set tsi prebias time */
+ if (pdata->tsi_prebias) {
+ data = pdata->tsi_prebias;
+ ret = pm860x_reg_write(i2c,
+ PM8607_TSI_PREBIAS, data);
+ if (ret < 0)
+ return -EINVAL;
+ }
+ /* set prebias & prechg time of pen detect */
+ data = 0;
+ data |= pdata->pen_prebias
+ & PM8607_PD_PREBIAS_MASK;
+ data |= (pdata->pen_prechg << 5)
+ & PM8607_PD_PRECHG_MASK;
+ if (data) {
+ ret = pm860x_reg_write(i2c,
+ PM8607_PD_PREBIAS, data);
+ if (ret < 0)
+ return -EINVAL;
+ }
+ res_x = pdata->res_x;
+ } else {
+ dev_err(&pdev->dev, "failed to get platform data\n");
+ return -EINVAL;
+ }
}
-
- touch = kzalloc(sizeof(struct pm860x_touch), GFP_KERNEL);
- if (touch == NULL)
+ /* enable GPADC */
+ ret = pm860x_set_bits(i2c, PM8607_GPADC_MISC1, PM8607_GPADC_EN,
+ PM8607_GPADC_EN);
+ if (ret)
+ return ret;
+
+ touch = devm_kzalloc(&pdev->dev, sizeof(struct pm860x_touch),
+ GFP_KERNEL);
+ if (!touch)
return -ENOMEM;
- dev_set_drvdata(&pdev->dev, touch);
- touch->idev = input_allocate_device();
- if (touch->idev == NULL) {
+ platform_set_drvdata(pdev, touch);
+
+ touch->idev = devm_input_allocate_device(&pdev->dev);
+ if (!touch->idev) {
dev_err(&pdev->dev, "Failed to allocate input device!\n");
- ret = -ENOMEM;
- goto out;
+ return -ENOMEM;
}
touch->idev->name = "88pm860x-touch";
@@ -158,15 +255,16 @@ static int __devinit pm860x_touch_probe(struct platform_device *pdev)
touch->idev->open = pm860x_touch_open;
touch->idev->close = pm860x_touch_close;
touch->chip = chip;
- touch->i2c = (chip->id == CHIP_PM8607) ? chip->client : chip->companion;
- touch->irq = irq + chip->irq_base;
- touch->res_x = pdata->res_x;
+ touch->i2c = i2c;
+ touch->irq = irq;
+ touch->res_x = res_x;
input_set_drvdata(touch->idev, touch);
- ret = request_threaded_irq(touch->irq, NULL, pm860x_touch_handler,
- IRQF_ONESHOT, "touch", touch);
+ ret = devm_request_threaded_irq(&pdev->dev, touch->irq, NULL,
+ pm860x_touch_handler, IRQF_ONESHOT,
+ "touch", touch);
if (ret < 0)
- goto out_irq;
+ return ret;
__set_bit(EV_ABS, touch->idev->evbit);
__set_bit(ABS_X, touch->idev->absbit);
@@ -184,29 +282,11 @@ static int __devinit pm860x_touch_probe(struct platform_device *pdev)
ret = input_register_device(touch->idev);
if (ret < 0) {
dev_err(chip->dev, "Failed to register touch!\n");
- goto out_rg;
+ return ret;
}
platform_set_drvdata(pdev, touch);
return 0;
-out_rg:
- free_irq(touch->irq, touch);
-out_irq:
- input_free_device(touch->idev);
-out:
- kfree(touch);
- return ret;
-}
-
-static int __devexit pm860x_touch_remove(struct platform_device *pdev)
-{
- struct pm860x_touch *touch = platform_get_drvdata(pdev);
-
- input_unregister_device(touch->idev);
- free_irq(touch->irq, touch);
- platform_set_drvdata(pdev, NULL);
- kfree(touch);
- return 0;
}
static struct platform_driver pm860x_touch_driver = {
@@ -215,20 +295,8 @@ static struct platform_driver pm860x_touch_driver = {
.owner = THIS_MODULE,
},
.probe = pm860x_touch_probe,
- .remove = __devexit_p(pm860x_touch_remove),
};
-
-static int __init pm860x_touch_init(void)
-{
- return platform_driver_register(&pm860x_touch_driver);
-}
-module_init(pm860x_touch_init);
-
-static void __exit pm860x_touch_exit(void)
-{
- platform_driver_unregister(&pm860x_touch_driver);
-}
-module_exit(pm860x_touch_exit);
+module_platform_driver(pm860x_touch_driver);
MODULE_DESCRIPTION("Touchscreen driver for Marvell Semiconductor 88PM860x");
MODULE_AUTHOR("Haojian Zhuang <haojian.zhuang@marvell.com>");