struct continuous {
u16 id; /* codec id */
u8 code; /* continuous code */
u8 reads; /* number of coord reads per read cycle */
u32 speed; /* number of coords per second */
};
/* continuous speed index */ staticint sp_idx; staticstruct gpio_desc *gpiod_irq;
/* * Pen sampling frequency (Hz) in continuous mode.
*/ staticint cont_rate = 200;
module_param(cont_rate, int, 0);
MODULE_PARM_DESC(cont_rate, "Sampling rate in continuous mode (Hz)");
/* * Pen down detection. * * This driver can either poll or use an interrupt to indicate a pen down * event. If the irq request fails then it will fall back to polling mode.
*/ staticint pen_int;
module_param(pen_int, int, 0);
MODULE_PARM_DESC(pen_int, "Pen down detection (1 = interrupt, 0 = polling)");
/* * Pressure readback. * * Set to 1 to read back pen down pressure
*/ staticint pressure;
module_param(pressure, int, 0);
MODULE_PARM_DESC(pressure, "Pressure readback (1 = pressure, 0 = no pressure)");
/* * AC97 touch data slot. * * Touch screen readback data ac97 slot
*/ staticint ac97_touch_slot = 5;
module_param(ac97_touch_slot, int, 0);
MODULE_PARM_DESC(ac97_touch_slot, "Touch screen data slot AC97 number");
if (cpu_is_pxa27x()) { while (pxa2xx_ac97_read_misr() & (1 << 2))
pxa2xx_ac97_read_modr();
} elseif (cpu_is_pxa3xx()) { for (count = 0; count < 16; count++)
pxa2xx_ac97_read_modr();
}
}
staticint wm97xx_acc_pen_down(struct wm97xx *wm)
{
u16 x, y, p = 0x100 | WM97XX_ADCSEL_PRES; int reads = 0; static u16 last, tries;
/* When the AC97 queue has been drained we need to allow time * to buffer up samples otherwise we end up spinning polling * for samples. The controller can't have a suitably low * threshold set to use the notifications it gives.
*/
msleep(1);
if (tries > 5) {
tries = 0; return RC_PENUP;
}
x = pxa2xx_ac97_read_modr(); if (x == last) {
tries++; return RC_AGAIN;
}
last = x; do { if (reads)
x = pxa2xx_ac97_read_modr();
y = pxa2xx_ac97_read_modr(); if (pressure)
p = pxa2xx_ac97_read_modr();
dev_dbg(wm->dev, "Raw coordinates: x=%x, y=%x, p=%x\n",
x, y, p);
/* coordinate is good */
tries = 0;
input_report_abs(wm->input_dev, ABS_X, x & 0xfff);
input_report_abs(wm->input_dev, ABS_Y, y & 0xfff);
input_report_abs(wm->input_dev, ABS_PRESSURE, p & 0xfff);
input_report_key(wm->input_dev, BTN_TOUCH, (p != 0));
input_sync(wm->input_dev);
reads++;
} while (reads < cinfo[sp_idx].reads);
up: return RC_PENDOWN | RC_AGAIN;
}
staticint wm97xx_acc_startup(struct wm97xx *wm)
{ int idx = 0, ret = 0;
/* check we have a codec */ if (wm->ac97 == NULL) return -ENODEV;
/* Go you big red fire engine */ for (idx = 0; idx < ARRAY_SIZE(cinfo); idx++) { if (wm->id != cinfo[idx].id) continue;
sp_idx = idx; if (cont_rate <= cinfo[idx].speed) break;
}
wm->acc_rate = cinfo[sp_idx].code;
wm->acc_slot = ac97_touch_slot;
dev_info(wm->dev, "mainstone accelerated touchscreen driver, %d samples/sec\n",
cinfo[sp_idx].speed);
if (pen_int) {
gpiod_irq = gpiod_get(wm->dev, "touch", GPIOD_IN); if (IS_ERR(gpiod_irq))
pen_int = 0;
}
if (pen_int) {
wm->pen_irq = gpiod_to_irq(gpiod_irq);
irq_set_irq_type(wm->pen_irq, IRQ_TYPE_EDGE_BOTH);
}
/* codec specific irq config */ if (pen_int) { switch (wm->id) { case WM9705_ID2: break; case WM9712_ID2: case WM9713_ID2: /* use PEN_DOWN GPIO 13 to assert IRQ on GPIO line 2 */
wm97xx_config_gpio(wm, WM97XX_GPIO_13, WM97XX_GPIO_IN,
WM97XX_GPIO_POL_HIGH,
WM97XX_GPIO_STICKY,
WM97XX_GPIO_WAKE);
wm97xx_config_gpio(wm, WM97XX_GPIO_2, WM97XX_GPIO_OUT,
WM97XX_GPIO_POL_HIGH,
WM97XX_GPIO_NOTSTICKY,
WM97XX_GPIO_NOWAKE); break; default:
dev_err(wm->dev, "pen down irq not supported on this device\n");
pen_int = 0; break;
}
}
return ret;
}
staticvoid wm97xx_acc_shutdown(struct wm97xx *wm)
{ /* codec specific deconfig */ if (pen_int) { if (gpiod_irq)
gpiod_put(gpiod_irq);
wm->pen_irq = 0;
}
}
Die Informationen auf dieser Webseite wurden
nach bestem Wissen sorgfältig zusammengestellt. Es wird jedoch weder Vollständigkeit, noch Richtigkeit,
noch Qualität der bereit gestellten Informationen zugesichert.
Bemerkung:
Die farbliche Syntaxdarstellung und die Messung sind noch experimentell.