static irqreturn_t lpc32xx_ts_interrupt(int irq, void *dev_id) { u32 tmp, rv[4], xs[4], ys[4]; int idx; struct lpc32xx_tsc *tsc = dev_id; struct input_dev *input = tsc->dev; tmp = tsc_readl(tsc, LPC32XX_TSC_STAT); if (tmp & LPC32XX_TSC_STAT_FIFO_OVRRN) { /* FIFO overflow - throw away samples */ lpc32xx_fifo_clear(tsc); return IRQ_HANDLED; } /* * Gather and normalize 4 samples. Pen-up events may have less * than 4 samples, but its ok to pop 4 and let the last sample * pen status check drop the samples. */ idx = 0; while (idx < 4 && !(tsc_readl(tsc, LPC32XX_TSC_STAT) & LPC32XX_TSC_STAT_FIFO_EMPTY)) { tmp = tsc_readl(tsc, LPC32XX_TSC_FIFO); xs[idx] = LPC32XX_TSC_ADCDAT_VALUE_MASK - LPC32XX_TSC_FIFO_NORMALIZE_X_VAL(tmp); ys[idx] = LPC32XX_TSC_ADCDAT_VALUE_MASK - LPC32XX_TSC_FIFO_NORMALIZE_Y_VAL(tmp); rv[idx] = tmp; idx++; } /* Data is only valid if pen is still down in last sample */ if (!(rv[3] & LPC32XX_TSC_FIFO_TS_P_LEVEL) && idx == 4) { /* Use average of 2nd and 3rd sample for position */ input_report_abs(input, ABS_X, (xs[1] + xs[2]) / 2); input_report_abs(input, ABS_Y, (ys[1] + ys[2]) / 2); input_report_key(input, BTN_TOUCH, 1); } else { input_report_key(input, BTN_TOUCH, 0); } input_sync(input); return IRQ_HANDLED; }
static void lpc32xx_setup_tsc(struct lpc32xx_tsc *tsc) { u32 tmp; clk_enable(tsc->clk); tmp = tsc_readl(tsc, LPC32XX_TSC_CON) & ~LPC32XX_TSC_ADCCON_POWER_UP; /* Set the TSC FIFO depth to 4 samples @ 10-bits per sample (max) */ tmp = LPC32XX_TSC_ADCCON_IRQ_TO_FIFO_4 | LPC32XX_TSC_ADCCON_X_SAMPLE_SIZE(10) | LPC32XX_TSC_ADCCON_Y_SAMPLE_SIZE(10); tsc_writel(tsc, LPC32XX_TSC_CON, tmp); /* These values are all preset */ tsc_writel(tsc, LPC32XX_TSC_SEL, LPC32XX_TSC_SEL_DEFVAL); tsc_writel(tsc, LPC32XX_TSC_MIN_X, LPC32XX_TSC_MIN_XY_VAL); tsc_writel(tsc, LPC32XX_TSC_MAX_X, LPC32XX_TSC_MAX_XY_VAL); tsc_writel(tsc, LPC32XX_TSC_MIN_Y, LPC32XX_TSC_MIN_XY_VAL); tsc_writel(tsc, LPC32XX_TSC_MAX_Y, LPC32XX_TSC_MAX_XY_VAL); /* Aux support is not used */ tsc_writel(tsc, LPC32XX_TSC_AUX_UTR, 0); tsc_writel(tsc, LPC32XX_TSC_AUX_MIN, 0); tsc_writel(tsc, LPC32XX_TSC_AUX_MAX, 0); /* * Set sample rate to about 240Hz per X/Y pair. A single measurement * consists of 4 pairs which gives about a 60Hz sample rate based on * a stable 32768Hz clock source. Values are in clocks. * Rate is (32768 / (RTR + XCONV + RTR + YCONV + DXP + TTR + UTR) / 4 */ tsc_writel(tsc, LPC32XX_TSC_RTR, 0x2); tsc_writel(tsc, LPC32XX_TSC_DTR, 0x2); tsc_writel(tsc, LPC32XX_TSC_TTR, 0x10); tsc_writel(tsc, LPC32XX_TSC_DXP, 0x4); tsc_writel(tsc, LPC32XX_TSC_UTR, 88); lpc32xx_fifo_clear(tsc); /* Enable automatic ts event capture */ tsc_writel(tsc, LPC32XX_TSC_CON, tmp | LPC32XX_TSC_ADCCON_AUTO_EN); }
static irqreturn_t lpc32xx_ts_interrupt(int irq, void *dev_id) { u32 tmp, rv[4], xs[4], ys[4]; int idx; struct lpc32xx_tsc *tsc = dev_id; struct input_dev *input = tsc->dev; tmp = tsc_readl(tsc, LPC32XX_TSC_STAT); if (tmp & LPC32XX_TSC_STAT_FIFO_OVRRN) { lpc32xx_fifo_clear(tsc); return IRQ_HANDLED; } idx = 0; while (idx < 4 && !(tsc_readl(tsc, LPC32XX_TSC_STAT) & LPC32XX_TSC_STAT_FIFO_EMPTY)) { tmp = tsc_readl(tsc, LPC32XX_TSC_FIFO); xs[idx] = LPC32XX_TSC_ADCDAT_VALUE_MASK - LPC32XX_TSC_FIFO_NORMALIZE_X_VAL(tmp); ys[idx] = LPC32XX_TSC_ADCDAT_VALUE_MASK - LPC32XX_TSC_FIFO_NORMALIZE_Y_VAL(tmp); rv[idx] = tmp; idx++; } if (!(rv[3] & LPC32XX_TSC_FIFO_TS_P_LEVEL) && idx == 4) { input_report_abs(input, ABS_X, (xs[1] + xs[2]) / 2); input_report_abs(input, ABS_Y, (ys[1] + ys[2]) / 2); input_report_key(input, BTN_TOUCH, 1); } else { input_report_key(input, BTN_TOUCH, 0); } input_sync(input); return IRQ_HANDLED; }
static void lpc32xx_setup_tsc(struct lpc32xx_tsc *tsc) { u32 tmp; clk_enable(tsc->clk); tmp = tsc_readl(tsc, LPC32XX_TSC_CON) & ~LPC32XX_TSC_ADCCON_POWER_UP; tmp = LPC32XX_TSC_ADCCON_IRQ_TO_FIFO_4 | LPC32XX_TSC_ADCCON_X_SAMPLE_SIZE(10) | LPC32XX_TSC_ADCCON_Y_SAMPLE_SIZE(10); tsc_writel(tsc, LPC32XX_TSC_CON, tmp); tsc_writel(tsc, LPC32XX_TSC_SEL, LPC32XX_TSC_SEL_DEFVAL); tsc_writel(tsc, LPC32XX_TSC_MIN_X, LPC32XX_TSC_MIN_XY_VAL); tsc_writel(tsc, LPC32XX_TSC_MAX_X, LPC32XX_TSC_MAX_XY_VAL); tsc_writel(tsc, LPC32XX_TSC_MIN_Y, LPC32XX_TSC_MIN_XY_VAL); tsc_writel(tsc, LPC32XX_TSC_MAX_Y, LPC32XX_TSC_MAX_XY_VAL); tsc_writel(tsc, LPC32XX_TSC_AUX_UTR, 0); tsc_writel(tsc, LPC32XX_TSC_AUX_MIN, 0); tsc_writel(tsc, LPC32XX_TSC_AUX_MAX, 0); tsc_writel(tsc, LPC32XX_TSC_RTR, 0x2); tsc_writel(tsc, LPC32XX_TSC_DTR, 0x2); tsc_writel(tsc, LPC32XX_TSC_TTR, 0x10); tsc_writel(tsc, LPC32XX_TSC_DXP, 0x4); tsc_writel(tsc, LPC32XX_TSC_UTR, 88); lpc32xx_fifo_clear(tsc); tsc_writel(tsc, LPC32XX_TSC_CON, tmp | LPC32XX_TSC_ADCCON_AUTO_EN); }