u16 x_akt;
u16 y_akt;
u16 u_akt;
+ u16 cal_auto_zero;
+ u16 cal_range_x;
+ u16 cal_range_y;
unsigned int stav;
u8 auto_calibration;
-};
-
+ u8 is_open;
-struct mx1ts mx1_ts;
+};
static inline void mx1ts_reg_set_mask(struct mx1ts *mts , unsigned int reg, u32 mask)
{
__raw_writel(val, mts->mx1ts_mem+reg );
}
+static inline void mx1ts_reg_clear_mask(struct mx1ts *mts , unsigned int reg, u32 mask)
+{
+ u32 val;
+ val = __raw_readl(mts->mx1ts_mem+reg);
+ val &= mask;
+ __raw_writel(val, mts->mx1ts_mem+reg );
+}
+
static inline void mx1ts_reg_write(struct mx1ts *mts, unsigned int reg, unsigned int val)
{
__raw_writel(val, mts->mx1ts_mem+reg);
- printk("mx1_touchscreen: zapisuji do : %p hodnotu %d\n",mts->mx1ts_mem+reg, val);
+ printk(KERN_ERR "mx1_touchscreen: zapisuji do : %p hodnotu %x\n",mts->mx1ts_mem+reg, val);
}
unsigned int out;
out = __raw_readl( mts->mx1ts_mem + reg );
- /*printk("mx1_touchscreen: ctu z %p : %d \n",mts->mx1ts_mem + reg, out);*/
+ /*printk(KERN_ERR "mx1_touchscreen: ctu z %p : %d \n",mts->mx1ts_mem + reg, out);*/
return out;
}
+static inline void mx1ts_flush_fifo(struct mx1ts *mts)
+{
+ int i;
+ for (i = 0; i < 12; i++)
+ if (mx1ts_reg_read(mts, ASP_ISTATR) & (ASP_PFF | ASP_PDR))
+ mx1ts_reg_read(mts, ASP_PADFIFO);
+}
+
+static void mx1ts_enable_auto_sample(struct mx1ts *mts)
+{
+ unsigned int value;
+
+ mx1ts_flush_fifo(mts);
+
+ value = mx1ts_reg_read(mts, ASP_ACNTLCR);
+
+ /* Set the mode to X then Y */
+ value &= ~ASP_MODE_MASK;
+ value |= ASP_MODE_ONLY_Y;
+
+ /* Enable auto zero. */
+ value |= ASP_AZE;
+
+ /* Enable auto sample. */
+ value |= ASP_AUTO;
+
+ /* Enable pen A/D. */
+ value |= ASP_PADE;
+ mx1ts_reg_write(mts, ASP_ACNTLCR, value);
+
+ /* Enable pen data ready and full interrupt. */
+ value = mx1ts_reg_read(mts, ASP_ICNTLR);
+ value |= ASP_PFFE | ASP_PDRE;
+ mx1ts_reg_write(mts, ASP_ICNTLR, value);
+}
+
+
static void mx1ts_disable_auto_sample(struct mx1ts *mts)
{
unsigned int value;
/* Enable pen touch interrupt. */
value = mx1ts_reg_read(mts, ASP_ICNTLR);
- value |= ASP_EDGE | ASP_PIRQE;
+ value |= /*ASP_POL detekuje zvednuti |*/ ASP_EDGE | ASP_PIRQE;
mx1ts_reg_write(mts, ASP_ICNTLR, value);
+ printk(KERN_ERR "mx1_touchscreen: aktivuji pen down interrupt \n");
}
static void mx1ts_disable_pen_touch_interrupt(struct mx1ts *mts)
value = mx1ts_reg_read(mts, ASP_ICNTLR);
value &= ~ASP_PIRQE;
mx1ts_reg_write(mts, ASP_ICNTLR, value);
+ printk(KERN_ERR "mx1_touchscreen: deaktivuji pen down interrupt \n");
}
static void mx1ts_enable_pen_up_interrupt(struct mx1ts *mts)
{
unsigned int value;
- /* Enable pen up interrupt. XXX: This feature is undocumented. */
value = mx1ts_reg_read(mts, ASP_ICNTLR);
- value |= ASP_PUIE;
+ value |= ASP_PUIE;
mx1ts_reg_write(mts, ASP_ICNTLR, value);
+ printk(KERN_ERR "mx1_touchscreen: aktivuji pen up interrupt \n");
}
static void mx1ts_disable_pen_up_interrupt(struct mx1ts *mts)
{
unsigned int value;
- /* Enable pen up interrupt. XXX: This feature is undocumented. */
+ /* Enable pen up interrupt. */
value = mx1ts_reg_read(mts, ASP_ICNTLR);
value &= ~ASP_PUIE;
mx1ts_reg_write(mts, ASP_ICNTLR, value);
+ printk(KERN_ERR "mx1_touchscreen: deaktivuji penup interrupt \n");
}
-static inline void mx1ts_flush_fifo(struct mx1ts *mts)
-{
- int i;
- for (i = 0; i < 12; i++)
- if (mx1ts_reg_read(mts, ASP_ISTATR) & (ASP_PFF | ASP_PDR))
- mx1ts_reg_read(mts, ASP_PADFIFO);
-}
+
static void mx1ts_start_auto_calibration(struct mx1ts *mts)
{
mx1ts_reg_write(mts, ASP_ICNTLR, value);
}
+static void mx1ts_reset_asp(struct mx1ts *mts)
+{
+ unsigned int value;
+
+ mx1ts_flush_fifo(mts);
+
+ /* Soft reset the ASP module */
+ mx1ts_reg_write(mts, ASP_ACNTLCR, ASP_SWRST);
+ /* Read back the reset value of the control register */
+ value = mx1ts_reg_read(mts, ASP_ACNTLCR);
+
+ /* Enable the clock and wait for a short while */
+ value |= ASP_CLKEN;
+ mx1ts_reg_write(mts, ASP_ACNTLCR, value);
+ udelay(100);
+
+ /* Set the value of the conrtol register. */
+ value = ASP_CLKEN | ASP_NM | ASP_SW6 | ASP_BGE;
+ mx1ts_reg_write(mts, ASP_ACNTLCR, value);
+
+ /* Set the clock divide ratio to 2. */
+ mx1ts_reg_write(mts, ASP_CLKDIV, 0x01);
+
+ /* Set the sample rate control register. These values should yield
+ * about 150 samples per second, which seems to give good smooth
+ * lines. */
+ value = (0x2 << ASP_DMCNT_SCALE) | /* Decimation ratio is 3 */
+ (0x1 << ASP_IDLECNT_SCALE) | /* Idle count is 1 clock */
+ (0x2 << ASP_DSCNT_SCALE); /* Data setup is 2 clocks */
+ mx1ts_reg_write(mts, ASP_PSMPLRG, value);
+
+ /* Disable the compare function. */
+ mx1ts_reg_write(mts, ASP_CMPCNTL, 0);
+}
+
static void mx1ts_evt_add(struct input_dev *idev, u8 p , u16 x, u16 y)
{
input_report_key(idev, BTN_TOUCH, p);
input_report_abs(idev, ABS_X, x);
input_report_abs(idev, ABS_Y, y);
/* input_report_abs(idev, ABS_PRESSURE, pressure);*/
- printk(KERN_ERR "ukladam hodnoty vystupu %i, %i, %i.\n", p, x, y);
+ /*printk(KERN_ERR "P %i X %i Y %i.\n", p, x, y);*/ /*devprint dev_dbg(zarizeni, co se vypisuje)*/
input_sync(idev);
}
+/*
+ * Handle the pen data ready interrupt, generated when pen data is
+ * in the FIFO.
+ */
+/*static irqreturn_t mx1ts_pendata_irq(int irq, void *dev_id)*/
static irqreturn_t mx1ts_pendata_irq(int irq, void *dev_id)
{
- u16 auto_zero;
- u16 mx1ts_cal_auto_zero;
+ struct mx1ts *mts = (struct mx1ts *)dev_id;
u16 mx1_cal_range_x;
u16 mx1_cal_range_y;
- u16 data;
+ static unsigned int auto_zero, pen_x, pen_y, pen_u;
+
+ /*struct mx1ts *mts = (struct mx1_ts *) dev_id;*/
+
mx1_cal_range_x = 1;
mx1_cal_range_y = 1;
-/* static unsigned int auto_zero, pen_x, pen_y, pen_u;*/
-
- struct mx1_ts *mts = (struct mx1_ts *) dev_id;
- /*printk("<1> mx1_touchscreen: mx1_pendata_irq interrupt recived from struct %p\n", mts);*/
-
- /*mx1ts_reg_write(mts, ASP_ICNTLR , ASP_PUIE | / ASP_EDGE |/ ASP_PIRQE);*/
-
- /*mx1ts_reg_set_mask(mts, ASP_ISTATR, ASP_PUIS);*/
-
- /*data = mx1ts_reg_read(mts, ASP_PADFIFO);*/
-
- /*mts->akt[mts->stav++] = data;*/
- /*printk("<1> mx1_touchscreen: FIFO data %i\n", data);*/
-
-
- if (mx1ts_reg_read(mts, ASP_ISTATR) & ASP_PUIS) {
- mx1ts_reg_set_mask(mts, ASP_ISTATR, ASP_PUIS);
+/* printk(KERN_ERR "mx1_touchscreen: mx1_pendata_irq interrupt recived from struct %p\n", mts);*/
+
+ if (mx1ts_reg_read(mts, ASP_ISTATR) & ASP_PUIS) { /*pen up interupt pending*/
+ mx1ts_reg_set_mask(mts, ASP_ISTATR, ASP_PUIS); /*clearing pen up interupt*/
- mx1ts_disable_auto_sample(mts);
+ mx1ts_disable_auto_sample(mts);
mx1ts_disable_pen_up_interrupt(mts);
mx1ts_enable_pen_touch_interrupt(mts);
- mx1ts_evt_add(mts, 0, 0, 0);
- printk(KERN_ERR "Zaplnena fifo.\n");
+ if(mts->is_open) /*report last known touch*/
+ mx1ts_evt_add(mts->ts_idev, 0, 0, 0);
+ printk(KERN_ERR "Pen up interrupt.\n");
mx1ts_flush_fifo(mts);
return IRQ_HANDLED;
}
-
- /*if (pmts->auto_calibration) {
+
+ if (mts->auto_calibration) {
unsigned int value;
- mx1_cal_auto_zero = mx1_reg_read(ASP_PADFIFO) & 0xFFFF;
- mx1_cal_range_x = mx1_reg_read(ASP_PADFIFO) & 0xFFFF;
- mx1_cal_range_y = mx1_reg_read(ASP_PADFIFO) & 0xFFFF;
+ mts->cal_auto_zero = mx1ts_reg_read(mts, ASP_PADFIFO) & 0xFFFF;
+ mts->cal_range_x = mx1ts_reg_read(mts, ASP_PADFIFO) & 0xFFFF;
+ mts->cal_range_y = mx1ts_reg_read(mts, ASP_PADFIFO) & 0xFFFF;
- if ((mx1_cal_auto_zero >= mx1_cal_range_x) ||
- (mx1_cal_auto_zero >= mx1_cal_range_y)) {
+ printk(KERN_ERR "Kalibrace cal_auto_zero %i.\n",mts->cal_auto_zero);
+ printk(KERN_ERR "Kalibrace cal_range_x %i.\n",mts->cal_range_x);
+ printk(KERN_ERR "Kalibrace cal_range_y %i.\n",mts->cal_range_y);
+
+ if ((mts->cal_auto_zero >= mts->cal_range_x) ||
+ (mts->cal_auto_zero >= mts->cal_range_y)) {
// Invalid data.
- mx1ts_start_auto_calibration();
- return IRQ_HANDLED;
+ printk(KERN_ERR "Invalid data.\n");
+ mx1ts_flush_fifo(mts); /*if there are some older data*/
+ mx1ts_start_auto_calibration(mts);
+ return IRQ_NONE; /* return IRQ_HANDLED; */
}
- mx1_cal_range_x -= mx1_cal_auto_zero;
- mx1_cal_range_y -= mx1_cal_auto_zero;
-
- value = mx1_reg_read(ASP_ACNTLCR);
- value &= ~0x04000000; // Undocumented.
- mx1_reg_write(ASP_ACNTLCR, value);
+
+ mts->cal_range_x -= mts->cal_auto_zero;
+ mts->cal_range_y -= mts->cal_auto_zero;
+
+
+
+ value = mx1ts_reg_read(mts, ASP_ACNTLCR); /*switching S0..S7 by internal logic*/
+ value &= ~0x04000000;
+ mx1ts_reg_write(mts, ASP_ACNTLCR, value);
- mx1_performing_auto_calibration = 0;
+ mts->auto_calibration = 0;
- mx1ts_enable_auto_sample();
- } else {*/
+ mx1ts_enable_auto_sample(mts);
+ } else {
// There could be more than one sample in the FIFO, but we're
// only going to read one per call. The interrupt will be
// generated as long as there is data in the FIFO.
}
auto_zero = mx1ts_reg_read(mts, ASP_PADFIFO);
- /*if (auto_zero > (mx1ts_cal_auto_zero + 0x200)) {
- return IRQ_HANDLED;
- }*/
-
- u16 pen_x = mx1ts_reg_read(mts, ASP_PADFIFO);
- u16 pen_y = mx1ts_reg_read(mts, ASP_PADFIFO);
- u16 pen_u = mx1ts_reg_read(mts, ASP_PADFIFO);
+ if (auto_zero > (mts->cal_auto_zero + 0x200)) {
+ return IRQ_HANDLED; /* TODO asi se nic nedeje */
+ }
- pen_x = (u32)(((pen_x - mx1ts_cal_auto_zero) << 16) /
- mx1_cal_range_x);
- pen_y = (u32)(((pen_y - mx1ts_cal_auto_zero) << 16) /
- mx1_cal_range_y);
+ pen_x = mx1ts_reg_read(mts, ASP_PADFIFO);
+ pen_y = mx1ts_reg_read(mts, ASP_PADFIFO);
+ pen_u = mx1ts_reg_read(mts, ASP_PADFIFO);
- mx1ts_evt_add(mts, pen_u, pen_x, pen_y);
- /*}*/
+ pen_x = (u32)(((pen_x - auto_zero) << 16) /
+ mts->cal_range_x);
+ pen_y = (u32)(((pen_y - auto_zero) << 16) /
+ mts->cal_range_y);
+
+ if(mts->is_open)
+ mx1ts_evt_add(mts->ts_idev, 1, pen_x, pen_y);
+ }
return IRQ_HANDLED;
}
-static void mx1ts_pokus_zapnout(struct mx1ts *mts) {
- mx1ts_reg_write(mts, ASP_CLKDIV, 0x1F); //clok divide register
- mx1ts_reg_write(mts, ASP_ICNTLR , ASP_PUIE | ASP_PDRE | ASP_PFFE |/* ASP_EDGE |*/ ASP_PIRQE); //interupt control register //0X00000833
- mx1ts_reg_write(mts, ASP_PSMPLRG, 0x0000487F); //pen a/d sample rate control register
- mx1ts_reg_write(mts,ASP_ACNTLCR, ASP_CLKEN | ASP_AZE | ASP_AUTO | (10<<12) | 3); //control register
-
-}
-
-static void mx1ts_enable_pen_up_irq(struct mx1ts *mts)
-{
- unsigned int value;
- printk(KERN_ERR "Pen up irq.\n");
-
- value = mx1ts_reg_read(mts, ASP_ICNTLR);
- value |= ASP_PUIE;
- mx1ts_reg_write(mts, ASP_ICNTLR, value);
- printk(KERN_ERR "Mely probehnout nejake zapisy.\n");
- printk(KERN_ERR "Na adresu %i\n",ASP_ICNTLR );
- printk(KERN_ERR "Hodnota %i\n",value );
-}
+/*
+ * Handle the touch interrupt, generated when the pen is pressed/
+ * released.
+ */
static irqreturn_t mx1ts_touch_irq(int irq, void *dev_id)
{
struct mx1ts *mts = (struct mx1ts *) dev_id;
+ printk(KERN_ERR "Prijat touch down irq \n");
+
/* Clear the interrupt. */
mx1ts_reg_set_mask(mts, ASP_ISTATR, ASP_PEN);
-// mx1ts_disable_pen_touch_interrupt();
-// mx1ts_start_auto_calibration();
-// mx1ts_enable_pen_up_irq(mts);
+ mx1ts_disable_pen_touch_interrupt(mts);
+ mx1ts_start_auto_calibration(mts);
+ mx1ts_enable_pen_up_interrupt(mts);
+
return IRQ_HANDLED;
}
static inline int mx1ts_enable_irqs(struct mx1ts *mts) //zaregistruje preruseni
{
int result;
-// int request_irq(unsigned int irq, void (*handler)(int, struct pt_regs *), unsigned long flags, const char *device);
-//static void mx1ts_pendata_int(int irq, void *dev_id, struct pt_regs *regs);
-//request_irq (irq, soc_intr, IRQF_SHARED, "SOC", (void *)s))
result = request_irq(ASP_PENDATA_IRQ,
mx1ts_pendata_irq,
/*IRQF_*/ 0,
static int mx1ts_on(struct mx1ts *mts)
{
int ret = 0;
-/* int err; //k check_region*/
if(!request_mem_region(ASP_BASE_ADDR, 0x38 , "mx1ts")) {
- printk(KERN_ERR "mx1ts: request_mem_region \tFAILED\n");
+ printk(KERN_ERR "mx1ts: request_mem_region \tFAILED\n");
+ return -1;
}
- printk("<1>mx1ts: request_mem_region \tOK\n");
+ printk(KERN_ERR "mx1ts: request_mem_region \tOK\n");
mts->mx1ts_mem = ioremap ( ASP_BASE_ADDR, 0x38);
- printk("<1>mx1ts: memory remaped on %p \n", mts->mx1ts_mem);
- //mx1ts_reset_asp();
+ printk(KERN_ERR "mx1ts: memory remaped on %p \n", mts->mx1ts_mem);
+
+
- printk("<1>mx1ts: enabling irqs\n");
+ printk(KERN_ERR "mx1ts: enabling irqs\n");
if ((ret = mx1ts_enable_irqs(mts)))
return ret;
- printk("<1>mx1ts: irqs enabled \tOK\n");
-
- mx1ts_pokus_zapnout(mts);
- printk("<1>mx1ts: vypada ze zapisy probehly\n");
-
- //mx1ts_evt_add(mts->ts_idev, 1, 2,3);
+ printk(KERN_ERR "mx1ts: irqs enabled \tOK\n");
+
+ mx1ts_reset_asp(mts);
+ printk(KERN_ERR "mx1ts: reset\tOK\n");
+
return 0;
}
-static int mx1ts_close(struct platform_dev *dev)
+static void mx1ts_close(struct input_dev *idev)
{
- return 0;
+ struct mx1ts *mts = dev_get_drvdata(idev->dev.parent);
+ mts->is_open = 0;
+ mx1ts_reset_asp(mts);
+ printk(KERN_ERR "mx1ts: reset\tOK\n");
+ mx1ts_disable_pen_touch_interrupt(mts);
+ mx1ts_disable_pen_up_interrupt(mts);
+
}
-static int mx1ts_open(struct platform_dev *dev)
+static int mx1ts_open(struct input_dev *idev)
{
+ struct mx1ts *mts = dev_get_drvdata(idev->dev.parent);
+ mts->is_open = 1;
+
+ mx1ts_enable_pen_touch_interrupt(mts);
+ printk(KERN_ERR "mx1ts: zapnuti touch interrupt\n");
return 0;
}
static int mx1ts_probe(struct platform_device *dev)
{
-
- //struct mx1ts *mts= &mx1_ts;
- struct mx1ts *mts;
+ struct mx1ts *mts;
struct input_dev *idev;
- int error, id, x_res, y_res;
+ int error, x_res, y_res;
-// mx1ts_disable_pen_touch_interrupt();
-// mx1ts_start_auto_calibration();
-// mx1ts_enable_pen_up_interrupt();
+ /* TODO jak poznat ze zarizeni je pritomne ? */
- mts = kzalloc(sizeof(struct mx1ts), GFP_KERNEL); //alokuje pamet
- idev = input_allocate_device();
+ mts = kzalloc(sizeof(struct mx1ts), GFP_KERNEL); /* alokuje pamet */
+ idev = input_allocate_device();
if (!mts || !idev) {
error = -ENOMEM;
+ printk(KERN_ERR "mx1ts: failed allocate memory for struct mx1ts or idev\n");
goto err_free_devs;
- return error; //XXX
+ return error;
}
- mx1_ts = *mts;
-
- mx1ts_on(mts);
-
- return 0;
+ mx1ts_on(mts); /* remaping registers, reseting device */
mts->ts_idev = idev;
//ucb->adcsync = adcsync;
}
printk(KERN_DEBUG "UCB1400: found IRQ %d\n", ucb->irq);*/
-// input_set_drvdata(idev, mx1_ts);
+ //input_set_drvdata(idev, mts); /*moznost ulozit ukazatel na trukturu do input_driver*/
+ platform_set_drvdata(dev, mts);
idev->dev.parent = &dev->dev;
idev->name = "MX1 touchscreen interface";
- idev->id.vendor = (unsigned int) 345;//mx1ts_reg_read(mx1_ts, AC97_VENDOR_ID1);
- idev->id.product = id;
+ idev->id.vendor = (unsigned int) 345; /*mx1ts_reg_read(mx1_ts, AC97_VENDOR_ID1);*/
+ idev->id.product = (unsigned int) 354; /*id;*/
idev->open = mx1ts_open;
idev->close = mx1ts_close;
idev->evbit[0] = BIT_MASK(EV_KEY) | BIT_MASK(EV_ABS);
idev->keybit[BIT_WORD(BTN_TOUCH)] = BIT_MASK(BTN_TOUCH);
- //idev->bustype = BUS_HOST;
-
- printk("<1> mx1ts: setting idev struct \tOK\t");
+ printk(KERN_ERR "mx1ts: setting idev struct \tOK\n");
-/* mx1ts_adc_enable(ucb);
- x_res = mx1ts_read_xres(ucb);
- y_res = mx1ts_read_yres(ucb);
- mx1ts_adc_disable(ucb);
- printk(KERN_DEBUG "UCB1400: x/y = %d/%d\n", x_res, y_res);*/
+ x_res = 35000;
+ y_res = 35000;
+ printk(KERN_DEBUG "mx1ts: x/y = %d/%d\n", x_res, y_res);
input_set_abs_params(idev, ABS_X, 0, x_res, 0, 0);
input_set_abs_params(idev, ABS_Y, 0, y_res, 0, 0);
input_set_abs_params(idev, ABS_PRESSURE, 0, 0, 0, 0);
-// error = input_register_device(idev);
-// if (error)
-// goto err_free_irq;
+ error = input_register_device(idev);
+ if (error) {
+ printk(KERN_ERR "mx1ts: error while register input device\n");
+ goto err_free_devs;
+ }
+
+ printk(KERN_ERR "mx1ts: input device registered \tOK\n");
-// dev_set_drvdata(dev, ucb);
return 0;
-// err_free_irq:
-// free_irq(ucb->irq, ucb);
- err_free_devs:
- input_free_device(idev);
+ err_free_devs:
+ printk(KERN_ERR "mx1ts: error in device probe \n");
+ /*input_free_device(idev);*/
kfree(mts);
return error;
-
static int mx1ts_remove(struct platform_device *dev)
{
- struct mx1_ts *mts = &mx1_ts;
+ struct mx1ts *mts = platform_get_drvdata(dev);
+
+ BUG_ON(mts == NULL);
- release_mem_region(ASP_BASE_ADDR, 0x40);
- iounmap(mx1_ts.mx1ts_mem);
free_irq(ASP_PENDATA_IRQ, mts);
free_irq(ASP_TOUCH_IRQ, mts);
- //input_free_device(mts->ts_idev);
+ input_free_device(mts->ts_idev);
+
+ iounmap(mts->mx1ts_mem);
+ release_mem_region(ASP_BASE_ADDR, 0x38);
+
kfree(mts);
- printk("<1> Removing driver \tOK\n");
+ printk(KERN_ERR "Removing driver \tOK\n");
return 0;
}