summaryrefslogtreecommitdiff
path: root/drivers
diff options
context:
space:
mode:
authorSammy He <r62914@freescale.com>2009-11-26 09:47:13 +0800
committerSammy He <r62914@freescale.com>2009-11-29 21:45:26 +0800
commitace2dc9b247db5463ac1a8a06c33239ebbe1079f (patch)
treecb5dbba9ee89c86f534e6fb3740fe8334e73b381 /drivers
parentdc188d771acf5df43aaecc5335b3c8f5834d663a (diff)
ENGR00118695 Fix touch screen cannot work sometimes
Fix touch screen cannot work sometimes issue: Use PD_IRQ mask to control irq to system, not PD_EN. Signed-off-by: Sammy He <r62914@freescale.com>
Diffstat (limited to 'drivers')
-rw-r--r--drivers/mxc/adc/imx_adc.c109
1 files changed, 90 insertions, 19 deletions
diff --git a/drivers/mxc/adc/imx_adc.c b/drivers/mxc/adc/imx_adc.c
index 11f0a66ee4bb..0ab8b918c9db 100644
--- a/drivers/mxc/adc/imx_adc.c
+++ b/drivers/mxc/adc/imx_adc.c
@@ -165,7 +165,17 @@ void imx_tsc_init(void)
(lastitemid << CQCR_LAST_ITEM_ID_SHIFT);
__raw_writel(reg, tsc_base + TCQCR);
+ /* Config idle for 4-wire */
+ reg = TSC_4WIRE_PRECHARGE;
+ __raw_writel(reg, tsc_base + TICR);
+
+ reg = TSC_4WIRE_TOUCH_DETECT;
+ __raw_writel(reg, tsc_base + TICR);
+
/* pen down enable */
+ reg = __raw_readl(tsc_base + TGCR);
+ reg |= TGCR_PD_EN | TGCR_PDB_EN;
+ __raw_writel(reg, tsc_base + TGCR);
reg = __raw_readl(tsc_base + TCQCR);
reg &= ~CQCR_PD_MSK;
__raw_writel(reg, tsc_base + TCQCR);
@@ -175,25 +185,42 @@ void imx_tsc_init(void)
/* Debounce time = dbtime*8 adc clock cycles */
reg = __raw_readl(tsc_base + TGCR);
- dbtime = 3;
+ dbtime = TGCR_PDBTIME128;
reg &= ~TGCR_PDBTIME_MASK;
reg |= dbtime << TGCR_PDBTIME_SHIFT;
- reg |= TGCR_SLPC;
+ reg |= TGCR_HSYNC_EN;
__raw_writel(reg, tsc_base + TGCR);
}
static irqreturn_t imx_adc_interrupt(int irq, void *dev_id)
{
- int reg;
+ unsigned long reg;
- /* disable pen down detect */
- reg = __raw_readl(tsc_base + TGCR);
- reg &= ~TGCR_PD_EN;
- __raw_writel(reg, tsc_base + TGCR);
+ if (__raw_readl(tsc_base + TGSR) & 0x4) {
+ /* deep sleep wakeup interrupt */
+ /* clear tgsr */
+ __raw_writel(0, tsc_base + TGSR);
+ /* clear deep sleep wakeup irq */
+ reg = __raw_readl(tsc_base + TGCR);
+ reg &= ~TGCR_SLPC;
+ __raw_writel(reg, tsc_base + TGCR);
+ /* un-mask pen down and pen down irq */
+ reg = __raw_readl(tsc_base + TCQCR);
+ reg &= ~CQCR_PD_MSK;
+ __raw_writel(reg, tsc_base + TCQCR);
+ reg = __raw_readl(tsc_base + TCQMR);
+ reg &= ~TCQMR_PD_IRQ_MSK;
+ __raw_writel(reg, tsc_base + TCQMR);
+ } else {
+ /* mask pen down detect irq */
+ reg = __raw_readl(tsc_base + TCQMR);
+ reg |= TCQMR_PD_IRQ_MSK;
+ __raw_writel(reg, tsc_base + TCQMR);
- ts_data_ready = 1;
- wake_up_interruptible(&tsq);
+ ts_data_ready = 1;
+ wake_up_interruptible(&tsq);
+ }
return IRQ_HANDLED;
}
@@ -252,10 +279,10 @@ enum IMX_ADC_STATUS imx_adc_read_ts(struct t_touch_screen *touch_sample,
reg |= CQCR_QSM_PEN;
__raw_writel(reg, tsc_base + TCQCR);
- /* PDEN and PDBEN */
- reg = __raw_readl(tsc_base + TGCR);
- reg |= (TGCR_PDB_EN | TGCR_PD_EN);
- __raw_writel(reg, tsc_base + TGCR);
+ /* unmask pen down detect irq */
+ reg = __raw_readl(tsc_base + TCQMR);
+ reg &= ~TCQMR_PD_IRQ_MSK;
+ __raw_writel(reg, tsc_base + TCQMR);
wait_event_interruptible(tsq, ts_data_ready);
while (!(__raw_readl(tsc_base + TCQSR) & CQSR_EOQ))
@@ -304,6 +331,14 @@ enum IMX_ADC_STATUS imx_adc_read_ts(struct t_touch_screen *touch_sample,
reg |= CQSR_EOQ;
__raw_writel(reg, tsc_base + TCQSR);
tsi_data = FQS_DATA;
+
+ /* Config idle for 4-wire */
+ reg = TSC_4WIRE_PRECHARGE;
+ __raw_writel(reg, tsc_base + TICR);
+
+ reg = TSC_4WIRE_TOUCH_DETECT;
+ __raw_writel(reg, tsc_base + TICR);
+
}
while (!(__raw_readl(tsc_base + TCQSR) & CQSR_EMPT)) {
@@ -549,6 +584,33 @@ EXPORT_SYMBOL(imx_adc_get_touch_sample);
*/
static int imx_adc_suspend(struct platform_device *pdev, pm_message_t state)
{
+ unsigned long reg;
+
+ /* Config idle for 4-wire */
+ reg = TSC_4WIRE_PRECHARGE;
+ __raw_writel(reg, tsc_base + TICR);
+
+ reg = TSC_4WIRE_TOUCH_DETECT;
+ __raw_writel(reg, tsc_base + TICR);
+
+ /* enable deep sleep wake up */
+ reg = __raw_readl(tsc_base + TGCR);
+ reg |= TGCR_SLPC;
+ __raw_writel(reg, tsc_base + TGCR);
+
+ /* mask pen down and pen down irq */
+ reg = __raw_readl(tsc_base + TCQCR);
+ reg |= CQCR_PD_MSK;
+ __raw_writel(reg, tsc_base + TCQCR);
+ reg = __raw_readl(tsc_base + TCQMR);
+ reg |= TCQMR_PD_IRQ_MSK;
+ __raw_writel(reg, tsc_base + TCQMR);
+
+ /* Set power mode to off */
+ reg = __raw_readl(tsc_base + TGCR) & ~TGCR_POWER_MASK;
+ reg |= TGCR_POWER_OFF;
+ __raw_writel(reg, tsc_base + TGCR);
+
if (device_may_wakeup(&pdev->dev)) {
enable_irq_wake(adc_data->irq);
} else {
@@ -568,6 +630,8 @@ static int imx_adc_suspend(struct platform_device *pdev, pm_message_t state)
*/
static int imx_adc_resume(struct platform_device *pdev)
{
+ unsigned long reg;
+
if (device_may_wakeup(&pdev->dev)) {
disable_irq_wake(adc_data->irq);
} else {
@@ -578,6 +642,12 @@ static int imx_adc_resume(struct platform_device *pdev)
wake_up_interruptible(&suspendq);
}
}
+
+ /* recover power mode */
+ reg = __raw_readl(tsc_base + TGCR) & ~TGCR_POWER_MASK;
+ reg |= TGCR_POWER_SAVE;
+ __raw_writel(reg, tsc_base + TGCR);
+
return 0;
}
@@ -689,9 +759,10 @@ enum IMX_ADC_STATUS imx_adc_convert(enum t_channel channel,
reg &= ~CQCR_QSM_MASK;
reg |= CQCR_QSM_PEN;
__raw_writel(reg, tsc_base + TCQCR);
- reg = __raw_readl(tsc_base + TGCR);
- reg |= TGCR_PDB_EN | TGCR_PD_EN;
- __raw_writel(reg, tsc_base + TGCR);
+
+ reg = __raw_readl(tsc_base + TCQMR);
+ reg &= ~TCQMR_PD_IRQ_MSK;
+ __raw_writel(reg, tsc_base + TCQMR);
}
break;
@@ -706,9 +777,9 @@ enum IMX_ADC_STATUS imx_adc_convert(enum t_channel channel,
reg |= CQCR_QSM_PEN;
__raw_writel(reg, tsc_base + TCQCR);
- reg = __raw_readl(tsc_base + TGCR);
- reg |= TGCR_PDB_EN | TGCR_PD_EN;
- __raw_writel(reg, tsc_base + TGCR);
+ reg = __raw_readl(tsc_base + TCQMR);
+ reg &= ~TCQMR_PD_IRQ_MSK;
+ __raw_writel(reg, tsc_base + TCQMR);
}
break;