diff options
author | Sammy He <r62914@freescale.com> | 2009-11-26 09:47:13 +0800 |
---|---|---|
committer | Sammy He <r62914@freescale.com> | 2009-11-29 21:45:26 +0800 |
commit | ace2dc9b247db5463ac1a8a06c33239ebbe1079f (patch) | |
tree | cb5dbba9ee89c86f534e6fb3740fe8334e73b381 | |
parent | dc188d771acf5df43aaecc5335b3c8f5834d663a (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>
-rw-r--r-- | drivers/mxc/adc/imx_adc.c | 109 |
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; |