OpenCores
URL https://opencores.org/ocsvn/or1k/or1k/trunk

Subversion Repositories or1k

[/] [or1k/] [trunk/] [linux/] [linux-2.4/] [drivers/] [char/] [au1000_ts.c] - Blame information for rev 1774

Go to most recent revision | Details | Compare with Previous | View Log

Line No. Rev Author Line
1 1275 phoenix
/*
2
 *      au1000_ts.c  --  Touch screen driver for the Alchemy Au1000's
3
 *                       SSI Port 0 talking to the ADS7846 touch screen
4
 *                       controller.
5
 *
6
 * Copyright 2001 MontaVista Software Inc.
7
 * Author: MontaVista Software, Inc.
8
 *              stevel@mvista.com or source@mvista.com
9
 *
10
 *  This program is free software; you can redistribute  it and/or modify it
11
 *  under  the terms of  the GNU General  Public License as published by the
12
 *  Free Software Foundation;  either version 2 of the  License, or (at your
13
 *  option) any later version.
14
 *
15
 *  THIS  SOFTWARE  IS PROVIDED   ``AS  IS'' AND   ANY  EXPRESS OR IMPLIED
16
 *  WARRANTIES,   INCLUDING, BUT NOT  LIMITED  TO, THE IMPLIED WARRANTIES OF
17
 *  MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.  IN
18
 *  NO  EVENT  SHALL   THE AUTHOR  BE    LIABLE FOR ANY   DIRECT, INDIRECT,
19
 *  INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
20
 *  NOT LIMITED   TO, PROCUREMENT OF  SUBSTITUTE GOODS  OR SERVICES; LOSS OF
21
 *  USE, DATA,  OR PROFITS; OR  BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON
22
 *  ANY THEORY OF LIABILITY, WHETHER IN  CONTRACT, STRICT LIABILITY, OR TORT
23
 *  (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
24
 *  THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
25
 *
26
 *  You should have received a copy of the  GNU General Public License along
27
 *  with this program; if not, write  to the Free Software Foundation, Inc.,
28
 *  675 Mass Ave, Cambridge, MA 02139, USA.
29
 *
30
 * Notes:
31
 *
32
 *  Revision history
33
 *    06.27.2001  Initial version
34
 */
35
 
36
#include <linux/module.h>
37
#include <linux/version.h>
38
 
39
#include <linux/init.h>
40
#include <linux/fs.h>
41
#include <linux/delay.h>
42
#include <linux/poll.h>
43
#include <linux/string.h>
44
#include <linux/ioport.h>       /* request_region */
45
#include <linux/interrupt.h>    /* mark_bh */
46
#include <asm/uaccess.h>        /* get_user,copy_to_user */
47
#include <asm/io.h>
48
#include <asm/au1000.h>
49
 
50
#define TS_NAME "au1000-ts"
51
#define TS_MAJOR 11
52
 
53
#define PFX TS_NAME
54
#define AU1000_TS_DEBUG 1
55
 
56
#ifdef AU1000_TS_DEBUG
57
#define dbg(format, arg...) printk(KERN_DEBUG PFX ": " format "\n" , ## arg)
58
#else
59
#define dbg(format, arg...) do {} while (0)
60
#endif
61
#define err(format, arg...) printk(KERN_ERR PFX ": " format "\n" , ## arg)
62
#define info(format, arg...) printk(KERN_INFO PFX ": " format "\n" , ## arg)
63
#define warn(format, arg...) printk(KERN_WARNING PFX ": " format "\n" , ## arg)
64
 
65
 
66
// SSI Status register bit defines
67
#define SSISTAT_BF    (1<<4)
68
#define SSISTAT_OF    (1<<3)
69
#define SSISTAT_UF    (1<<2)
70
#define SSISTAT_DONE  (1<<1)
71
#define SSISTAT_BUSY  (1<<0)
72
 
73
// SSI Interrupt Pending and Enable register bit defines
74
#define SSIINT_OI     (1<<3)
75
#define SSIINT_UI     (1<<2)
76
#define SSIINT_DI     (1<<1)
77
 
78
// SSI Address/Data register bit defines
79
#define SSIADAT_D         (1<<24)
80
#define SSIADAT_ADDR_BIT  16
81
#define SSIADAT_ADDR_MASK (0xff<<SSIADAT_ADDR_BIT)
82
#define SSIADAT_DATA_BIT  0
83
#define SSIADAT_DATA_MASK (0xfff<<SSIADAT_DATA_BIT)
84
 
85
// SSI Enable register bit defines
86
#define SSIEN_CD (1<<1)
87
#define SSIEN_E  (1<<0)
88
 
89
// SSI Config register bit defines
90
#define SSICFG_AO (1<<24)
91
#define SSICFG_DO (1<<23)
92
#define SSICFG_ALEN_BIT 20
93
#define SSICFG_ALEN_MASK (0x7<<SSICFG_ALEN_BIT)
94
#define SSICFG_DLEN_BIT 16
95
#define SSICFG_DLEN_MASK (0xf<<SSICFG_DLEN_BIT)
96
#define SSICFG_DD (1<<11)
97
#define SSICFG_AD (1<<10)
98
#define SSICFG_BM_BIT 8
99
#define SSICFG_BM_MASK (0x3<<SSICFG_BM_BIT)
100
#define SSICFG_CE (1<<7)
101
#define SSICFG_DP (1<<6)
102
#define SSICFG_DL (1<<5)
103
#define SSICFG_EP (1<<4)
104
 
105
// Bus Turnaround Selection
106
#define SCLK_HOLD_HIGH 0
107
#define SCLK_HOLD_LOW  1
108
#define SCLK_CYCLE     2
109
 
110
/*
111
 * Default config for SSI0:
112
 *
113
 *   - transmit MSBit first
114
 *   - expect MSBit first on data receive
115
 *   - address length 7 bits
116
 *   - expect data length 12 bits
117
 *   - do not disable Direction bit
118
 *   - do not disable Address bits
119
 *   - SCLK held low during bus turnaround
120
 *   - Address and Data bits clocked out on falling edge of SCLK
121
 *   - Direction bit high is a read, low is a write
122
 *   - Direction bit precedes Address bits
123
 *   - Active low enable signal
124
 */
125
 
126
#define DEFAULT_SSI_CONFIG \
127
    (SSICFG_AO | SSICFG_DO | (6<<SSICFG_ALEN_BIT) | (11<<SSICFG_DLEN_BIT) |\
128
    (SCLK_HOLD_LOW<<SSICFG_BM_BIT) | SSICFG_DP | SSICFG_EP)
129
 
130
 
131
// ADS7846 Control Byte bit defines
132
#define ADS7846_ADDR_BIT  4
133
#define ADS7846_ADDR_MASK (0x7<<ADS7846_ADDR_BIT)
134
#define   ADS7846_MEASURE_X  (0x5<<ADS7846_ADDR_BIT)
135
#define   ADS7846_MEASURE_Y  (0x1<<ADS7846_ADDR_BIT)
136
#define   ADS7846_MEASURE_Z1 (0x3<<ADS7846_ADDR_BIT)
137
#define   ADS7846_MEASURE_Z2 (0x4<<ADS7846_ADDR_BIT)
138
#define ADS7846_8BITS     (1<<3)
139
#define ADS7846_12BITS    0
140
#define ADS7846_SER       (1<<2)
141
#define ADS7846_DFR       0
142
#define ADS7846_PWR_BIT   0
143
#define   ADS7846_PD      0
144
#define   ADS7846_ADC_ON  (0x1<<ADS7846_PWR_BIT)
145
#define   ADS7846_REF_ON  (0x2<<ADS7846_PWR_BIT)
146
#define   ADS7846_REF_ADC_ON (0x3<<ADS7846_PWR_BIT)
147
 
148
#define MEASURE_12BIT_X \
149
    (ADS7846_MEASURE_X | ADS7846_12BITS | ADS7846_DFR | ADS7846_PD)
150
#define MEASURE_12BIT_Y \
151
    (ADS7846_MEASURE_Y | ADS7846_12BITS | ADS7846_DFR | ADS7846_PD)
152
#define MEASURE_12BIT_Z1 \
153
    (ADS7846_MEASURE_Z1 | ADS7846_12BITS | ADS7846_DFR | ADS7846_PD)
154
#define MEASURE_12BIT_Z2 \
155
    (ADS7846_MEASURE_Z2 | ADS7846_12BITS | ADS7846_DFR | ADS7846_PD)
156
 
157
typedef enum {
158
        IDLE = 0,
159
        ACQ_X,
160
        ACQ_Y,
161
        ACQ_Z1,
162
        ACQ_Z2
163
} acq_state_t;
164
 
165
/* +++++++++++++ Lifted from include/linux/h3600_ts.h ++++++++++++++*/
166
typedef struct {
167
        unsigned short pressure;  // touch pressure
168
        unsigned short x;         // calibrated X
169
        unsigned short y;         // calibrated Y
170
        unsigned short millisecs; // timestamp of this event
171
} TS_EVENT;
172
 
173
typedef struct {
174
        int xscale;
175
        int xtrans;
176
        int yscale;
177
        int ytrans;
178
        int xyswap;
179
} TS_CAL;
180
 
181
/* Use 'f' as magic number */
182
#define IOC_MAGIC  'f'
183
 
184
#define TS_GET_RATE             _IO(IOC_MAGIC, 8)
185
#define TS_SET_RATE             _IO(IOC_MAGIC, 9)
186
#define TS_GET_CAL              _IOR(IOC_MAGIC, 10, TS_CAL)
187
#define TS_SET_CAL              _IOW(IOC_MAGIC, 11, TS_CAL)
188
 
189
/* +++++++++++++ Done lifted from include/linux/h3600_ts.h +++++++++*/
190
 
191
 
192
#define EVENT_BUFSIZE 128
193
 
194
/*
195
 * Which pressure equation to use from ADS7846 datasheet.
196
 * The first equation requires knowing only the X plate
197
 * resistance, but needs 4 measurements (X, Y, Z1, Z2).
198
 * The second equation requires knowing both X and Y plate
199
 * resistance, but only needs 3 measurements (X, Y, Z1).
200
 * The second equation is preferred because of the shorter
201
 * acquisition time required.
202
 */
203
enum {
204
        PRESSURE_EQN_1 = 0,
205
        PRESSURE_EQN_2
206
};
207
 
208
 
209
/*
210
 * The touch screen's X and Y plate resistances, used by
211
 * pressure equations.
212
 */
213
#define DEFAULT_X_PLATE_OHMS 580
214
#define DEFAULT_Y_PLATE_OHMS 580
215
 
216
/*
217
 * Pen up/down pressure resistance thresholds.
218
 *
219
 * FIXME: these are bogus and will have to be found empirically.
220
 *
221
 * These are hysteresis points. If pen state is up and pressure
222
 * is greater than pen-down threshold, pen transitions to down.
223
 * If pen state is down and pressure is less than pen-up threshold,
224
 * pen transitions to up. If pressure is in-between, pen status
225
 * doesn't change.
226
 *
227
 * This wouldn't be needed if PENIRQ* from the ADS7846 were
228
 * routed to an interrupt line on the Au1000. This would issue
229
 * an interrupt when the panel is touched.
230
 */
231
#define DEFAULT_PENDOWN_THRESH_OHMS 100
232
#define DEFAULT_PENUP_THRESH_OHMS    80
233
 
234
typedef struct {
235
        int baudrate;
236
        u32 clkdiv;
237
        acq_state_t acq_state;            // State of acquisition state machine
238
        int x_raw, y_raw, z1_raw, z2_raw; // The current raw acquisition values
239
        TS_CAL cal;                       // Calibration values
240
        // The X and Y plate resistance, needed to calculate pressure
241
        int x_plate_ohms, y_plate_ohms;
242
        // pressure resistance at which pen is considered down/up
243
        int pendown_thresh_ohms;
244
        int penup_thresh_ohms;
245
        int pressure_eqn;                 // eqn to use for pressure calc
246
        int pendown;                      // 1 = pen is down, 0 = pen is up
247
        TS_EVENT event_buf[EVENT_BUFSIZE];// The event queue
248
        int nextIn, nextOut;
249
        int event_count;
250
        struct fasync_struct *fasync;     // asynch notification
251
        struct timer_list acq_timer;      // Timer for triggering acquisitions
252
        wait_queue_head_t wait;           // read wait queue
253
        spinlock_t lock;
254
        struct tq_struct chug_tq;
255
} au1000_ts_t;
256
 
257
static au1000_ts_t au1000_ts;
258
 
259
 
260
static inline u32
261
calc_clkdiv(int baud)
262
{
263
        u32 sys_busclk =
264
                (get_au1x00_speed() / (int)(inl(SYS_POWERCTRL)&0x03) + 2);
265
        return (sys_busclk / (2 * baud)) - 1;
266
}
267
 
268
static inline int
269
calc_baudrate(u32 clkdiv)
270
{
271
        u32 sys_busclk =
272
                (get_au1x00_speed() / (int)(inl(SYS_POWERCTRL)&0x03) + 2);
273
        return sys_busclk / (2 * (clkdiv + 1));
274
}
275
 
276
 
277
/*
278
 * This is a bottom-half handler that is scheduled after
279
 * raw X,Y,Z1,Z2 coordinates have been acquired, and does
280
 * the following:
281
 *
282
 *   - computes touch screen pressure resistance
283
 *   - if pressure is above a threshold considered to be pen-down:
284
 *         - compute calibrated X and Y coordinates
285
 *         - queue a new TS_EVENT
286
 *         - signal asynchronously and wake up any read
287
 */
288
static void
289
chug_raw_data(void* private)
290
{
291
        au1000_ts_t* ts = (au1000_ts_t*)private;
292
        TS_EVENT event;
293
        int Rt, Xcal, Ycal;
294
        unsigned long flags;
295
 
296
        // timestamp this new event.
297
        event.millisecs = jiffies;
298
 
299
        // Calculate touch pressure resistance
300
        if (ts->pressure_eqn == PRESSURE_EQN_2) {
301
                Rt = (ts->x_plate_ohms * ts->x_raw *
302
                      (4096 - ts->z1_raw)) / ts->z1_raw;
303
                Rt -= (ts->y_plate_ohms * ts->y_raw);
304
                Rt = (Rt + 2048) >> 12; // round up to nearest ohm
305
        } else {
306
                Rt = (ts->x_plate_ohms * ts->x_raw *
307
                      (ts->z2_raw - ts->z1_raw)) / ts->z1_raw;
308
                Rt = (Rt + 2048) >> 12; // round up to nearest ohm
309
        }
310
 
311
        // hysteresis
312
        if (!ts->pendown && Rt > ts->pendown_thresh_ohms)
313
                ts->pendown = 1;
314
        else if (ts->pendown && Rt < ts->penup_thresh_ohms)
315
                ts->pendown = 0;
316
 
317
        if (ts->pendown) {
318
                // Pen is down
319
                // Calculate calibrated X,Y
320
                Xcal = ((ts->cal.xscale * ts->x_raw) >> 8) + ts->cal.xtrans;
321
                Ycal = ((ts->cal.yscale * ts->y_raw) >> 8) + ts->cal.ytrans;
322
 
323
                event.x = (unsigned short)Xcal;
324
                event.y = (unsigned short)Ycal;
325
                event.pressure = (unsigned short)Rt;
326
 
327
                // add this event to the event queue
328
                spin_lock_irqsave(&ts->lock, flags);
329
                ts->event_buf[ts->nextIn++] = event;
330
                if (ts->nextIn == EVENT_BUFSIZE)
331
                        ts->nextIn = 0;
332
                if (ts->event_count < EVENT_BUFSIZE) {
333
                        ts->event_count++;
334
                } else {
335
                        // throw out the oldest event
336
                        if (++ts->nextOut == EVENT_BUFSIZE)
337
                                ts->nextOut = 0;
338
                }
339
                spin_unlock_irqrestore(&ts->lock, flags);
340
 
341
                // async notify
342
                if (ts->fasync)
343
                        kill_fasync(&ts->fasync, SIGIO, POLL_IN);
344
                // wake up any read call
345
                if (waitqueue_active(&ts->wait))
346
                        wake_up_interruptible(&ts->wait);
347
        }
348
}
349
 
350
 
351
/*
352
 * Raw X,Y,pressure acquisition timer function. This triggers
353
 * the start of a new acquisition. Its duration between calls
354
 * is the touch screen polling rate.
355
 */
356
static void
357
au1000_acq_timer(unsigned long data)
358
{
359
        au1000_ts_t* ts = (au1000_ts_t*)data;
360
        unsigned long flags;
361
 
362
        spin_lock_irqsave(&ts->lock, flags);
363
 
364
        // start acquisition with X coordinate
365
        ts->acq_state = ACQ_X;
366
        // start me up
367
        outl(SSIADAT_D | (MEASURE_12BIT_X << SSIADAT_ADDR_BIT), SSI0_ADATA);
368
 
369
        // schedule next acquire
370
        ts->acq_timer.expires = jiffies + HZ / 100;
371
        add_timer(&ts->acq_timer);
372
 
373
        spin_unlock_irqrestore(&ts->lock, flags);
374
}
375
 
376
static void
377
ssi0_interrupt(int irq, void *dev_id, struct pt_regs *regs)
378
{
379
        au1000_ts_t *ts = (au1000_ts_t*)dev_id;
380
        u32 stat, int_stat, data;
381
 
382
        spin_lock(&ts->lock);
383
 
384
        stat = inl(SSI0_STATUS);
385
        // clear sticky status bits
386
        outl(stat & (SSISTAT_OF|SSISTAT_UF|SSISTAT_DONE), SSI0_STATUS);
387
 
388
        int_stat = inl(SSI0_INT);
389
        // clear sticky intr status bits
390
        outl(int_stat & (SSIINT_OI|SSIINT_UI|SSIINT_DI), SSI0_INT);
391
 
392
        if ((int_stat & (SSIINT_OI|SSIINT_UI|SSIINT_DI)) != SSIINT_DI) {
393
                if (int_stat & SSIINT_OI)
394
                        err("overflow");
395
                if (int_stat & SSIINT_UI)
396
                        err("underflow");
397
                spin_unlock(&ts->lock);
398
                return;
399
        }
400
 
401
        data = inl(SSI0_ADATA) & SSIADAT_DATA_MASK;
402
 
403
        switch (ts->acq_state) {
404
        case IDLE:
405
                break;
406
        case ACQ_X:
407
                ts->x_raw = data;
408
                ts->acq_state = ACQ_Y;
409
                // trigger Y acq
410
                outl(SSIADAT_D | (MEASURE_12BIT_Y << SSIADAT_ADDR_BIT),
411
                     SSI0_ADATA);
412
                break;
413
        case ACQ_Y:
414
                ts->y_raw = data;
415
                ts->acq_state = ACQ_Z1;
416
                // trigger Z1 acq
417
                outl(SSIADAT_D | (MEASURE_12BIT_Z1 << SSIADAT_ADDR_BIT),
418
                     SSI0_ADATA);
419
                break;
420
        case ACQ_Z1:
421
                ts->z1_raw = data;
422
                if (ts->pressure_eqn == PRESSURE_EQN_2) {
423
                        // don't acq Z2, using 2nd eqn for touch pressure
424
                        ts->acq_state = IDLE;
425
                        // got the raw stuff, now mark BH
426
                        queue_task(&ts->chug_tq, &tq_immediate);
427
                        mark_bh(IMMEDIATE_BH);
428
                } else {
429
                        ts->acq_state = ACQ_Z2;
430
                        // trigger Z2 acq
431
                        outl(SSIADAT_D | (MEASURE_12BIT_Z2<<SSIADAT_ADDR_BIT),
432
                             SSI0_ADATA);
433
                }
434
                break;
435
        case ACQ_Z2:
436
                ts->z2_raw = data;
437
                ts->acq_state = IDLE;
438
                // got the raw stuff, now mark BH
439
                queue_task(&ts->chug_tq, &tq_immediate);
440
                mark_bh(IMMEDIATE_BH);
441
                break;
442
        }
443
 
444
        spin_unlock(&ts->lock);
445
}
446
 
447
 
448
/* +++++++++++++ File operations ++++++++++++++*/
449
 
450
static int
451
au1000_fasync(int fd, struct file *filp, int mode)
452
{
453
        au1000_ts_t* ts = (au1000_ts_t*)filp->private_data;
454
        return fasync_helper(fd, filp, mode, &ts->fasync);
455
}
456
 
457
static int
458
au1000_ioctl(struct inode * inode, struct file *filp,
459
             unsigned int cmd, unsigned long arg)
460
{
461
        au1000_ts_t* ts = (au1000_ts_t*)filp->private_data;
462
 
463
        switch(cmd) {
464
        case TS_GET_RATE:       /* TODO: what is this? */
465
                break;
466
        case TS_SET_RATE:       /* TODO: what is this? */
467
                break;
468
        case TS_GET_CAL:
469
                copy_to_user((char *)arg, (char *)&ts->cal, sizeof(TS_CAL));
470
                break;
471
        case TS_SET_CAL:
472
                copy_from_user((char *)&ts->cal, (char *)arg, sizeof(TS_CAL));
473
                break;
474
        default:
475
                err("unknown cmd %04x", cmd);
476
                return -EINVAL;
477
        }
478
 
479
        return 0;
480
}
481
 
482
static unsigned int
483
au1000_poll(struct file * filp, poll_table * wait)
484
{
485
        au1000_ts_t* ts = (au1000_ts_t*)filp->private_data;
486
        poll_wait(filp, &ts->wait, wait);
487
        if (ts->event_count)
488
                return POLLIN | POLLRDNORM;
489
        return 0;
490
}
491
 
492
static ssize_t
493
au1000_read(struct file * filp, char * buf, size_t count, loff_t * l)
494
{
495
        au1000_ts_t* ts = (au1000_ts_t*)filp->private_data;
496
        unsigned long flags;
497
        TS_EVENT event;
498
        int i;
499
 
500
        if (ts->event_count == 0) {
501
                if (filp->f_flags & O_NONBLOCK)
502
                        return -EAGAIN;
503
                interruptible_sleep_on(&ts->wait);
504
                if (signal_pending(current))
505
                        return -ERESTARTSYS;
506
        }
507
 
508
        for (i = count;
509
             i >= sizeof(TS_EVENT);
510
             i -= sizeof(TS_EVENT), buf += sizeof(TS_EVENT)) {
511
                if (ts->event_count == 0)
512
                        break;
513
                spin_lock_irqsave(&ts->lock, flags);
514
                event = ts->event_buf[ts->nextOut++];
515
                if (ts->nextOut == EVENT_BUFSIZE)
516
                        ts->nextOut = 0;
517
                if (ts->event_count)
518
                        ts->event_count--;
519
                spin_unlock_irqrestore(&ts->lock, flags);
520
                copy_to_user(buf, &event, sizeof(TS_EVENT));
521
        }
522
 
523
        return count - i;
524
}
525
 
526
 
527
static int
528
au1000_open(struct inode * inode, struct file * filp)
529
{
530
        au1000_ts_t* ts;
531
        unsigned long flags;
532
 
533
        filp->private_data = ts = &au1000_ts;
534
 
535
        spin_lock_irqsave(&ts->lock, flags);
536
 
537
        // setup SSI0 config
538
        outl(DEFAULT_SSI_CONFIG, SSI0_CONFIG);
539
 
540
        // clear out SSI0 status bits
541
        outl(SSISTAT_OF|SSISTAT_UF|SSISTAT_DONE, SSI0_STATUS);
542
        // clear out SSI0 interrupt pending bits
543
        outl(SSIINT_OI|SSIINT_UI|SSIINT_DI, SSI0_INT);
544
 
545
        // enable SSI0 interrupts
546
        outl(SSIINT_OI|SSIINT_UI|SSIINT_DI, SSI0_INT_ENABLE);
547
 
548
        /*
549
         * init bh handler that chugs the raw data (calibrates and
550
         * calculates touch pressure).
551
         */
552
        ts->chug_tq.routine = chug_raw_data;
553
        ts->chug_tq.data = ts;
554
        ts->pendown = 0; // pen up
555
 
556
        // flush event queue
557
        ts->nextIn = ts->nextOut = ts->event_count = 0;
558
 
559
        // Start acquisition timer function
560
        init_timer(&ts->acq_timer);
561
        ts->acq_timer.function = au1000_acq_timer;
562
        ts->acq_timer.data = (unsigned long)ts;
563
        ts->acq_timer.expires = jiffies + HZ / 100;
564
        add_timer(&ts->acq_timer);
565
 
566
        spin_unlock_irqrestore(&ts->lock, flags);
567
        MOD_INC_USE_COUNT;
568
        return 0;
569
}
570
 
571
static int
572
au1000_release(struct inode * inode, struct file * filp)
573
{
574
        au1000_ts_t* ts = (au1000_ts_t*)filp->private_data;
575
        unsigned long flags;
576
 
577
        au1000_fasync(-1, filp, 0);
578
        del_timer_sync(&ts->acq_timer);
579
 
580
        spin_lock_irqsave(&ts->lock, flags);
581
        // disable SSI0 interrupts
582
        outl(0, SSI0_INT_ENABLE);
583
        spin_unlock_irqrestore(&ts->lock, flags);
584
 
585
        MOD_DEC_USE_COUNT;
586
        return 0;
587
}
588
 
589
 
590
static struct file_operations ts_fops = {
591
        read:           au1000_read,
592
        poll:           au1000_poll,
593
        ioctl:          au1000_ioctl,
594
        fasync:         au1000_fasync,
595
        open:           au1000_open,
596
        release:        au1000_release,
597
};
598
 
599
/* +++++++++++++ End File operations ++++++++++++++*/
600
 
601
 
602
int __init
603
au1000ts_init_module(void)
604
{
605
        au1000_ts_t* ts = &au1000_ts;
606
        int ret;
607
 
608
        /* register our character device */
609
        if ((ret = register_chrdev(TS_MAJOR, TS_NAME, &ts_fops)) < 0) {
610
                err("can't get major number");
611
                return ret;
612
        }
613
        info("registered");
614
 
615
        memset(ts, 0, sizeof(au1000_ts_t));
616
        init_waitqueue_head(&ts->wait);
617
        spin_lock_init(&ts->lock);
618
 
619
        if (!request_region(virt_to_phys((void*)SSI0_STATUS), 0x100, TS_NAME)) {
620
                err("SSI0 ports in use");
621
                return -ENXIO;
622
        }
623
 
624
        if ((ret = request_irq(AU1000_SSI0_INT, ssi0_interrupt,
625
                               SA_SHIRQ | SA_INTERRUPT, TS_NAME, ts))) {
626
                err("could not get IRQ");
627
                return ret;
628
        }
629
 
630
        // initial calibration values
631
        ts->cal.xscale = -93;
632
        ts->cal.xtrans = 346;
633
        ts->cal.yscale = -64;
634
        ts->cal.ytrans = 251;
635
 
636
        // init pen up/down hysteresis points
637
        ts->pendown_thresh_ohms = DEFAULT_PENDOWN_THRESH_OHMS;
638
        ts->penup_thresh_ohms = DEFAULT_PENUP_THRESH_OHMS;
639
        ts->pressure_eqn = PRESSURE_EQN_2;
640
        // init X and Y plate resistances
641
        ts->x_plate_ohms = DEFAULT_X_PLATE_OHMS;
642
        ts->y_plate_ohms = DEFAULT_Y_PLATE_OHMS;
643
 
644
        // set GPIO to SSI0 function
645
        outl(inl(SYS_PINFUNC) & ~1, SYS_PINFUNC);
646
 
647
        // enable SSI0 clock and bring SSI0 out of reset
648
        outl(0, SSI0_CONTROL);
649
        udelay(1000);
650
        outl(SSIEN_E, SSI0_CONTROL);
651
        udelay(100);
652
 
653
        // FIXME: is this a working baudrate?
654
        ts->clkdiv = 0;
655
        ts->baudrate = calc_baudrate(ts->clkdiv);
656
        outl(ts->clkdiv, SSI0_CLKDIV);
657
 
658
        info("baudrate = %d Hz", ts->baudrate);
659
 
660
        return 0;
661
}
662
 
663
void
664
au1000ts_cleanup_module(void)
665
{
666
        // disable clocks and hold in reset
667
        outl(SSIEN_CD, SSI0_CONTROL);
668
        free_irq(AU1000_SSI0_INT, &au1000_ts);
669
        release_region(virt_to_phys((void*)SSI0_STATUS), 0x100);
670
        unregister_chrdev(TS_MAJOR, TS_NAME);
671
}
672
 
673
/* Module information */
674
MODULE_AUTHOR("Steve Longerbeam, stevel@mvista.com, www.mvista.com");
675
MODULE_DESCRIPTION("Au1000/ADS7846 Touch Screen Driver");
676
 
677
module_init(au1000ts_init_module);
678
module_exit(au1000ts_cleanup_module);

powered by: WebSVN 2.1.0

© copyright 1999-2024 OpenCores.org, equivalent to Oliscience, all rights reserved. OpenCores®, registered trademark.