Skip to contentSkip to conversation

input: touchscreen: use polling mode in 88pm860x

PATCH New Haojian Zhuang 1 participant 6 messages Apr 6, 2011 1 message not in the archive

Subsystems (4)
lore
Share & tools
lore

A message that is not in the archive (sent off-list or not yet received): 2011040601

#1 lore raw

PATCH 1/6 input: touchscreen: use polling mode in 88pm860x

Measuring point on touchscreen with IRQ mode can only monitor pen-down event. If finger is moving on touchscreen, it can't be monitored by IRQ pen-down event. So switch to polling mode after pen-down event.

---
 drivers/input/touchscreen/88pm860x-ts.c |   82 +++++++++++++++++++++++-------
 1 files changed, 63 insertions(+), 19 deletions(-)
drivers/input/touchscreen/88pm860x-ts.c +63 -19
index b3aebc2..fe12f61 100644
@@ -12,13 +12,25 @@
 #include <linux/module.h>
 #include <linux/platform_device.h>
 #include <linux/i2c.h>
+#include <linux/slab.h>
 #include <linux/input.h>
 #include <linux/mfd/88pm860x.h>
-#include <linux/slab.h>
 
 #define MEAS_LEN		(8)
 #define ACCURATE_BIT		(12)
 
+/*
+ * While 32KHz hardware timer is used for scheduler, we always assign HZ
+ * to 128. It means that 1 tick costs 7.8msec.
+ */
+#define MEASURE_INTERVAL_MS	(7)
+
+/* debounce register */
+#define DEBOUNCE		(0x0A)
+
+#define PD_DEBOUNCE_0MSEC	(0)
+#define PD_DEBOUNCE_MASK	(3)
+
 /* touch register */
 #define MEAS_EN3		(0x52)
 
@@ -39,22 +51,27 @@
 #define MEAS_TSIZ2_EN		(1 << 7)
 
 struct pm860x_touch {
-	struct input_dev *idev;
-	struct i2c_client *i2c;
-	struct pm860x_chip *chip;
-	int irq;
-	int res_x;		/* resistor of Xplate */
+	struct input_dev	*idev;
+	struct i2c_client	*i2c;
+	struct pm860x_chip	*chip;
+	struct delayed_work	poll_work;
+	struct mutex		lock;
+
+	int			irq;
+	int			res_x;		/* resistor of Xplate */
 };
 
-static irqreturn_t pm860x_touch_handler(int irq, void *data)
+static void pm860x_poll_work(struct work_struct *work)
 {
-	struct pm860x_touch *touch = data;
+	struct pm860x_touch *touch = container_of(work, struct pm860x_touch,
+						  poll_work.work);
 	struct pm860x_chip *chip = touch->chip;
+	int x, y, z1, z2, rt = 0;
+	int ret, pen_down, interval;
 	unsigned char buf[MEAS_LEN];
-	int x, y, pen_down;
-	int z1, z2, rt = 0;
-	int ret;
+	struct timeval start, end;
 
+	do_gettimeofday(&start);
 	ret = pm860x_bulk_read(touch->i2c, MEAS_TSIX_1, MEAS_LEN, buf);
 	if (ret < 0)
 		goto out;
@@ -77,30 +94,54 @@ static irqreturn_t pm860x_touch_handler(int irq, void *data)
 		input_report_abs(touch->idev, ABS_PRESSURE, rt);
 		input_report_key(touch->idev, BTN_TOUCH, 1);
 		dev_dbg(chip->dev, "pen down at [%d, %d].\n", x, y);
+
+		do_gettimeofday(&end);
+		interval = (end.tv_sec - start.tv_sec) * 1000000 +
+			(end.tv_usec - start.tv_usec) / 1000;
+		interval = (interval < MEASURE_INTERVAL_MS)
+			? (MEASURE_INTERVAL_MS - interval) : 0;
+		schedule_delayed_work(&touch->poll_work,
+				      msecs_to_jiffies(interval));
 	} else {
 		input_report_abs(touch->idev, ABS_PRESSURE, 0);
 		input_report_key(touch->idev, BTN_TOUCH, 0);
 		dev_dbg(chip->dev, "pen release\n");
+		mutex_unlock(&touch->lock);
 	}
 	input_sync(touch->idev);
 
 out:
+	return;
+}
+
+static irqreturn_t pm860x_touch_handler(int irq, void *data)
+{
+	struct pm860x_touch *touch = data;
+	int ret;
+
+	ret = pm860x_reg_read(touch->i2c, PM8607_STATUS_1);
+	dev_dbg(touch->chip->dev, "pen status:%d\n", (ret & PM8607_STATUS_PEN)
+		? 1 : 0);
+	if ((ret & PM8607_STATUS_PEN) == 0)
+		return IRQ_HANDLED;
+
+	mutex_lock(&touch->lock);
+	pm860x_poll_work(&touch->poll_work.work);
 	return IRQ_HANDLED;
 }
 
 static int pm860x_touch_open(struct input_dev *dev)
 {
 	struct pm860x_touch *touch = input_get_drvdata(dev);
-	int data, ret;
+	int data;
 
+	/* set debounce time with 0ms */
+	pm860x_set_bits(touch->i2c, DEBOUNCE, PD_DEBOUNCE_MASK,
+			PD_DEBOUNCE_0MSEC);
 	data = MEAS_PD_EN | MEAS_TSIX_EN | MEAS_TSIY_EN
 		| MEAS_TSIZ1_EN | MEAS_TSIZ2_EN;
-	ret = pm860x_set_bits(touch->i2c, MEAS_EN3, data, data);
-	if (ret < 0)
-		goto out;
+	pm860x_set_bits(touch->i2c, MEAS_EN3, data, data);
 	return 0;
-out:
-	return ret;
 }
 
 static void pm860x_touch_close(struct input_dev *dev)
@@ -152,16 +193,17 @@ static int __devinit pm860x_touch_probe(struct platform_device *pdev)
 	}
 
 	touch->idev->name = "88pm860x-touch";
-	touch->idev->phys = "88pm860x/input0";
+	touch->idev->phys = "88pm860x/input1";
 	touch->idev->id.bustype = BUS_I2C;
 	touch->idev->dev.parent = &pdev->dev;
 	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->irq = irq;
 	touch->res_x = pdata->res_x;
 	input_set_drvdata(touch->idev, touch);
+	mutex_init(&touch->lock);
 
 	ret = request_threaded_irq(touch->irq, NULL, pm860x_touch_handler,
 				   IRQF_ONESHOT, "touch", touch);
@@ -188,6 +230,7 @@ static int __devinit pm860x_touch_probe(struct platform_device *pdev)
 	}
 
 	platform_set_drvdata(pdev, touch);
+	INIT_DELAYED_WORK(&touch->poll_work, pm860x_poll_work);
 	return 0;
 out_rg:
 	free_irq(touch->irq, touch);
@@ -202,6 +245,7 @@ static int __devexit pm860x_touch_remove(struct platform_device *pdev)
 {
 	struct pm860x_touch *touch = platform_get_drvdata(pdev);
 
+	flush_scheduled_work();
 	input_unregister_device(touch->idev);
 	free_irq(touch->irq, touch);
 	platform_set_drvdata(pdev, NULL);
Signature · 1 line
1.5.6.5
#2 lore raw

PATCH 2/6 input: touchscreen: move initialization in 88pm860x

Move the GPADC initialization code from mfd driver to touch driver.

---
 drivers/input/touchscreen/88pm860x-ts.c |   44 +++++++++++++++++++++-----
 drivers/mfd/88pm860x-core.c             |   51 -------------------------------
 2 files changed, 35 insertions(+), 60 deletions(-)
drivers/input/touchscreen/88pm860x-ts.c +35 -9
index fe12f61..ea7abaa 100644
@@ -14,6 +14,7 @@
 #include <linux/i2c.h>
 #include <linux/slab.h>
 #include <linux/input.h>
+#include <linux/mfd/core.h>
 #include <linux/mfd/88pm860x.h>
 
 #define MEAS_LEN		(8)
@@ -154,11 +155,40 @@ static void pm860x_touch_close(struct input_dev *dev)
 	pm860x_set_bits(touch->i2c, MEAS_EN3, data, 0);
 }
 
+static void __devinit pm860x_gpadc_init(struct i2c_client *i2c,
+					struct pm860x_touch_pdata *pdata)
+{
+	int data;
+
+	/* 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)
+		pm860x_reg_write(i2c, PM8607_GPADC_MISC1, data);
+
+	/* set tsi prebias time */
+	if (pdata->tsi_prebias) {
+		data = pdata->tsi_prebias;
+		pm860x_reg_write(i2c, PM8607_TSI_PREBIAS, data);
+	}
+
+	/* 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)
+		pm860x_reg_write(i2c, PM8607_PD_PREBIAS, data);
+
+	pm860x_set_bits(i2c, PM8607_GPADC_MISC1,
+			PM8607_GPADC_EN, PM8607_GPADC_EN);
+}
+
 static int __devinit 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 *touch;
 	int irq, ret;
@@ -169,13 +199,8 @@ 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) {
+	pdata = mfd_get_data(pdev);
+	if (pdata == NULL) {
 		dev_err(&pdev->dev, "touchscreen data is missing\n");
 		return -EINVAL;
 	}
@@ -229,6 +254,7 @@ static int __devinit pm860x_touch_probe(struct platform_device *pdev)
 		goto out_rg;
 	}
 
+	pm860x_gpadc_init(touch->i2c, pdata);
 	platform_set_drvdata(pdev, touch);
 	INIT_DELAYED_WORK(&touch->poll_work, pm860x_poll_work);
 	return 0;
drivers/mfd/88pm860x-core.c +0 -51

63 lines not on this page · raw message

Signature · 1 line
1.5.6.5
#3 lore raw

PATCH 3/6 rtc: add 88pm860x rtc

Support RTC component in 88PM860x. Also support synchronize time from 88PM860x RTC to another RTC device. It should be implemented in sync callback API.

While 88PM860x RTC is enabled, it can do RTC calibration to gurantee enough power is supplied on VRTC domain of 88PM860x.

---
 drivers/mfd/88pm860x-core.c  |   30 +++
 drivers/rtc/Kconfig          |   10 +
 drivers/rtc/Makefile         |    1 +
 drivers/rtc/rtc-88pm860x.c   |  430 ++++++++++++++++++++++++++++++++++++++++++
 include/linux/mfd/88pm860x.h |    6 +
 5 files changed, 477 insertions(+), 0 deletions(-)
 create mode 100644 drivers/rtc/rtc-88pm860x.c
drivers/mfd/88pm860x-core.c +30 -0
index c73ffdf..63d1c54 100644
@@ -57,6 +57,10 @@ static struct resource regulator_resources[] __initdata = {
 	{PM8607_ID_LDO15, PM8607_ID_LDO15, "ldo-15", IORESOURCE_IO,},
 };
 
+static struct resource rtc_resources[] __initdata = {
+	{PM8607_IRQ_RTC, PM8607_IRQ_RTC, "rtc", IORESOURCE_IRQ,},
+};
+
 static struct resource touch_resources[] __initdata = {
 	{PM8607_IRQ_PEN, PM8607_IRQ_PEN, "touch", IORESOURCE_IRQ,},
 };
@@ -126,6 +130,10 @@ static struct mfd_cell regulator_devs[] __initdata = {
 	{"88pm860x-regulator", 17,},
 };
 
+static struct mfd_cell rtc_devs[] __initdata = {
+	{"88pm860x-rtc", -1,},
+};
+
 static struct mfd_cell touch_devs[] __initdata = {
 	{"88pm860x-touch", -1,},
 };
@@ -148,6 +156,7 @@ static struct pm860x_led_pdata led_pdata[ARRAY_SIZE(led_devs)];
 static struct regulator_init_data regulator_pdata[ARRAY_SIZE(regulator_devs)];
 static struct pm860x_touch_pdata touch_pdata;
 static struct pm860x_power_pdata power_pdata;
+static struct pm860x_rtc_pdata rtc_pdata;
 
 struct pm860x_irq_data {
 	int	reg;
@@ -585,6 +594,26 @@ out:
 	return;
 }
 
+static void __devinit device_rtc_init(struct pm860x_chip *chip,
+				      struct i2c_client *i2c,
+				      struct pm860x_platform_data *pdata)
+{
+	int ret;
+
+	if ((pdata == NULL) || (pdata->rtc == NULL))
+		return;
+
+	memcpy(&rtc_pdata, pdata->rtc, sizeof(struct pm860x_rtc_pdata));
+	rtc_devs[0].mfd_data = &rtc_pdata;
+	rtc_devs[0].num_resources = ARRAY_SIZE(rtc_resources);
+	rtc_devs[0].resources = &rtc_resources[0];
+	ret = mfd_add_devices(chip->dev, 0, &rtc_devs[0],
+			      ARRAY_SIZE(rtc_devs), &rtc_resources[0],
+			      chip->irq_base);
+	if (ret < 0)
+		dev_err(chip->dev, "Failed to add rtc subdev\n");
+}
+
 static void __devinit device_touch_init(struct pm860x_chip *chip,
 					struct i2c_client *i2c,
 					struct pm860x_platform_data *pdata)
@@ -713,6 +742,7 @@ static void __devinit device_8607_init(struct pm860x_chip *chip,
 		goto out;
 
 	device_regulator_init(chip, i2c, pdata);
+	device_rtc_init(chip, i2c, pdata);
 	device_onkey_init(chip, i2c, pdata);
 	device_touch_init(chip, i2c, pdata);
 	device_power_init(chip, i2c, pdata);
drivers/rtc/Kconfig +10 -0
index e187887..286f51e 100644
@@ -128,6 +128,16 @@ comment "I2C RTC drivers"
 
 if I2C
 
+config RTC_DRV_88PM860X
+	tristate "Marvell 88PM860x"
+	depends on RTC_CLASS && I2C && MFD_88PM860X
+	help
+	  If you say yes here you get support for RTC function in Marvell
+	  88PM860x chips.
+
+	  This driver can also be built as a module. If so, the module
+	  will be called rtc-88pm860x.
+
 config RTC_DRV_DS1307
 	tristate "Dallas/Maxim DS1307/37/38/39/40, ST M41T00, EPSON RX-8025"
 	help
drivers/rtc/Makefile +1 -0
index ca91c3c..e3d6fb0 100644
@@ -15,6 +15,7 @@ rtc-core-$(CONFIG_RTC_INTF_SYSFS) += rtc-sysfs.o
 
 # Keep the list ordered.
 
+obj-$(CONFIG_RTC_DRV_88PM860X)  += rtc-88pm860x.o
 obj-$(CONFIG_RTC_DRV_AB3100)	+= rtc-ab3100.o
 obj-$(CONFIG_RTC_DRV_AB8500)	+= rtc-ab8500.o
 obj-$(CONFIG_RTC_DRV_AT32AP700X)+= rtc-at32ap700x.o
drivers/rtc/rtc-88pm860x.c new file +430 -0

430 lines not on this page · raw message

include/linux/mfd/88pm860x.h +6 -0
index 8fba797..63b4fb8 100644
@@ -330,6 +330,11 @@ struct pm860x_led_pdata {
 	unsigned long	flags;
 };
 
+struct pm860x_rtc_pdata {
+	int		(*sync)(unsigned int ticks);
+	int		vrtc;
+};
+
 struct pm860x_touch_pdata {
 	int		gpadc_prebias;
 	int		slot_cycle;
@@ -349,6 +354,7 @@ struct pm860x_power_pdata {
 struct pm860x_platform_data {
 	struct pm860x_backlight_pdata	*backlight;
 	struct pm860x_led_pdata		*led;
+	struct pm860x_rtc_pdata		*rtc;
 	struct pm860x_touch_pdata	*touch;
 	struct pm860x_power_pdata	*power;
 	struct regulator_init_data	*regulator;
Signature · 1 line
1.5.6.5
#4 lore raw

PATCH 4/6 input: set the long press detection in 88pm860x onkey

Move the long-press detection from onkey handler to probe function. Avoid unnecessary I2C operation in onkey handler.

---
 drivers/input/misc/88pm860x_onkey.c |    6 +++---
 1 files changed, 3 insertions(+), 3 deletions(-)
drivers/input/misc/88pm860x_onkey.c +3 -3
index 3dca3c1..1abc77e 100644
@@ -50,9 +50,6 @@ static irqreturn_t pm860x_onkey_handler(int irq, void *data)
 	ret &= ONKEY_STATUS;
 	input_report_key(info->idev, KEY_POWER, ret);
 	input_sync(info->idev);
-
-	/* Enable 8-second long onkey detection */
-	pm860x_set_bits(info->i2c, PM8607_WAKEUP, 3, LONG_ONKEY_EN);
 	return IRQ_HANDLED;
 }
 
@@ -105,6 +102,9 @@ static int __devinit pm860x_onkey_probe(struct platform_device *pdev)
 	}
 
 	platform_set_drvdata(pdev, info);
+
+	/* Enable 8-second long onkey detection */
+	pm860x_set_bits(info->i2c, PM8607_WAKEUP, 3, LONG_ONKEY_EN);
 	return 0;
 
 out_irq:
Signature · 1 line
1.5.6.5
#5 lore raw

PATCH 5/6 w1: add DS278x slave driver

Append DS278x slave driver.

---
 drivers/w1/slaves/Kconfig     |   13 +++
 drivers/w1/slaves/Makefile    |    1 +
 drivers/w1/slaves/w1_ds278x.c |  184 +++++++++++++++++++++++++++++++++++++++++
 drivers/w1/w1_family.h        |    3 +
 4 files changed, 201 insertions(+), 0 deletions(-)
 create mode 100644 drivers/w1/slaves/w1_ds278x.c
drivers/w1/slaves/Kconfig +13 -0
index f0c9096..d737aa9 100644
@@ -61,6 +61,19 @@ config W1_SLAVE_DS2760
 
 	  If you are unsure, say N.
 
+config W1_SLAVE_DS278x
+	tristate "Dallas 278x battery monitor chip"
+	depends on W1
+	help
+	  If you enable this you will have the DS278x battery monitor
+	  chip support.
+
+	  The battery monitor chip is used in many batteries/devices
+	  as the one who is responsible for charging/discharging/monitoring
+	  Li+ batteries.
+
+	  If you are unsure, say N.
+
 config W1_SLAVE_BQ27000
 	tristate "BQ27000 slave support"
 	depends on W1
drivers/w1/slaves/Makefile +1 -0
index 3c76350..bcc134b 100644
@@ -8,4 +8,5 @@ obj-$(CONFIG_W1_SLAVE_DS2423)	+= w1_ds2423.o
 obj-$(CONFIG_W1_SLAVE_DS2431)	+= w1_ds2431.o
 obj-$(CONFIG_W1_SLAVE_DS2433)	+= w1_ds2433.o
 obj-$(CONFIG_W1_SLAVE_DS2760)	+= w1_ds2760.o
+obj-$(CONFIG_W1_SLAVE_DS278x)	+= w1_ds278x.o
 obj-$(CONFIG_W1_SLAVE_BQ27000)	+= w1_bq27000.o
drivers/w1/slaves/w1_ds278x.c new file +184 -0

184 lines not on this page · raw message

drivers/w1/w1_family.h +3 -0
index f3b636d..0f0b58c 100644
@@ -36,6 +36,9 @@
 #define W1_THERM_DS18B20 	0x28
 #define W1_EEPROM_DS2431	0x2D
 #define W1_FAMILY_DS2760	0x30
+#define W1_BATTMON_DS2780	0x32
+#define W1_BATTMON_DS2781	0x3D
+#define W1_BATTMON_DS2783	0x34
 
 #define MAXNAMELEN		32
 
Signature · 1 line
1.5.6.5
#6 lore raw

PATCH 6/6 mfd: pxa-w1: MFD driver for PXA 1wire control + DS1WM chip

This driver provides registers and IRQ of PXA3xx chips to the ds1wm driver.

---
 drivers/mfd/Kconfig  |    7 ++
 drivers/mfd/Makefile |    1 +
 drivers/mfd/pxa-w1.c |  149 ++++++++++++++++++++++++++++++++++++++++++++++++++
 3 files changed, 157 insertions(+), 0 deletions(-)
 create mode 100644 drivers/mfd/pxa-w1.c
drivers/mfd/Kconfig +7 -0
index 9a46d64..56a3c64 100644
@@ -34,6 +34,13 @@ config MFD_88PM860X
 	  select individual components like voltage regulators, RTC and
 	  battery-charger under the corresponding menus.
 
+config MFD_PXA_DS1WM
+	tristate "Support DS1WM chip on Marvell silicons"
+	select MFD_CORE
+	help
+	  This core driver provides register access for PXA_DS1WM.
+	  Actual functionality is handled by the ds1wm drivers.
+
 config MFD_SM501
 	tristate "Support for Silicon Motion SM501"
 	 ---help---
drivers/mfd/Makefile +1 -0
index ef489f2..7999c56 100644
@@ -4,6 +4,7 @@
 
 88pm860x-objs			:= 88pm860x-core.o 88pm860x-i2c.o
 obj-$(CONFIG_MFD_88PM860X)	+= 88pm860x.o
+obj-$(CONFIG_MFD_PXA_DS1WM)	+= pxa-w1.o
 obj-$(CONFIG_MFD_SM501)		+= sm501.o
 obj-$(CONFIG_MFD_ASIC3)		+= asic3.o tmio_core.o
 obj-$(CONFIG_MFD_SH_MOBILE_SDHI)		+= sh_mobile_sdhi.o
drivers/mfd/pxa-w1.c new file +149 -0

149 lines not on this page · raw message

Signature · 1 line
1.5.6.5