/* * Release touchscreen resources. Disable IRQs. */ static void ucb1x00_ts_close(struct input_dev *idev) { struct ucb1x00_ts *ts = input_get_drvdata(idev); if (ts->rtask) kthread_stop(ts->rtask); ucb1x00_enable(ts->ucb); ucb1x00_free_irq(ts->ucb, UCB_IRQ_TSPX, ts); ucb1x00_reg_write(ts->ucb, UCB_TS_CR, 0); ucb1x00_disable(ts->ucb); }
/* * Switch to Y position mode and measure X plate. We switch the plate * configuration in pressure mode, then switch to position mode. This * gives a faster response time. Even so, we need to wait about 55us * for things to stabilise. */ static inline unsigned int ucb1x00_ts_read_ypos(struct ucb1x00_ts *ts) { if (machine_is_collie()) ucb1x00_io_write(ts->ucb, 0, COLLIE_TC35143_GPIO_TBL_CHK); else { ucb1x00_reg_write(ts->ucb, UCB_TS_CR, UCB_TS_CR_TSMY_GND | UCB_TS_CR_TSPY_POW | UCB_TS_CR_MODE_PRES | UCB_TS_CR_BIAS_ENA); ucb1x00_reg_write(ts->ucb, UCB_TS_CR, UCB_TS_CR_TSMY_GND | UCB_TS_CR_TSPY_POW | UCB_TS_CR_MODE_PRES | UCB_TS_CR_BIAS_ENA); } ucb1x00_reg_write(ts->ucb, UCB_TS_CR, UCB_TS_CR_TSMY_GND | UCB_TS_CR_TSPY_POW | UCB_TS_CR_MODE_POS | UCB_TS_CR_BIAS_ENA); udelay(55); return ucb1x00_adc_read(ts->ucb, UCB_ADC_INP_TSPX, ts->adcsync); }
/* * Try to probe our interrupt, rather than relying on lots of * hard-coded machine dependencies. For reference, the expected * IRQ mappings are: * * Machine Default IRQ * adsbitsy IRQ_GPCIN4 * cerf IRQ_GPIO_UCB1200_IRQ * flexanet IRQ_GPIO_GUI * freebird IRQ_GPIO_FREEBIRD_UCB1300_IRQ * graphicsclient ADS_EXT_IRQ(8) * graphicsmaster ADS_EXT_IRQ(8) * lart LART_IRQ_UCB1200 * omnimeter IRQ_GPIO23 * pfs168 IRQ_GPIO_UCB1300_IRQ * simpad IRQ_GPIO_UCB1300_IRQ * shannon SHANNON_IRQ_GPIO_IRQ_CODEC * yopy IRQ_GPIO_UCB1200_IRQ */ static int __init ucb1x00_detect_irq(struct ucb1x00 *ucb) { unsigned long mask; mask = probe_irq_on(); if (!mask) return NO_IRQ; /* * Enable the ADC interrupt. */ ucb1x00_reg_write(ucb, UCB_IE_RIS, UCB_IE_ADC); ucb1x00_reg_write(ucb, UCB_IE_FAL, UCB_IE_ADC); ucb1x00_reg_write(ucb, UCB_IE_CLEAR, 0xffff); ucb1x00_reg_write(ucb, UCB_IE_CLEAR, 0); /* * Cause an ADC interrupt. */ ucb1x00_reg_write(ucb, UCB_ADC_CR, UCB_ADC_ENA); ucb1x00_reg_write(ucb, UCB_ADC_CR, UCB_ADC_ENA | UCB_ADC_START); /* * Wait for the conversion to complete. */ while ((ucb1x00_reg_read(ucb, UCB_ADC_DATA) & UCB_ADC_DAT_VAL) == 0); ucb1x00_reg_write(ucb, UCB_ADC_CR, 0); /* * Disable and clear interrupt. */ ucb1x00_reg_write(ucb, UCB_IE_RIS, 0); ucb1x00_reg_write(ucb, UCB_IE_FAL, 0); ucb1x00_reg_write(ucb, UCB_IE_CLEAR, 0xffff); ucb1x00_reg_write(ucb, UCB_IE_CLEAR, 0); /* * Read triggered interrupt. */ return probe_irq_off(mask); }