S3C2440 Linux touch screen driver

Source: Internet
Author: User

VM-RedHat 9.0

Board: fl2440, linux-2.6.12

Arm-Linux-GCC: 3.4.1

Line 1 in the Code. If drag is not supported, you can obtain the stroke coordinates, but the icons on the LCD do not respond. I do not know why.

# Include <Linux/config. h> # include <Linux/module. h> # include <Linux/moduleparam. h> # include <Linux/kernel. h> # include <Linux/sched. h> # include <Linux/init. h> # include <Linux/device. h> # include <Linux/miscdevice. h> # include <Linux/delay. h> # include <Linux/poll. h> # include <Linux/spinlock. h> # include <Linux/interrupt. h> # include <Linux/delay. h> # include <Linux/devfs_fs_kernel.h> # include <ASM/hardware/clock. h> # Inc Lude <ASM/hardware. h> # include <ASM/Io. h> # include <ASM/ARCH/regs-gpio.h> // ym_sen output drive enabling, xp_sen, yp_sen output drive disabling // s3c2410_adctsc_xy_pst (3) -- manual measurement in the X and Y directions, waiting for interruption mode // x = 0. Set adctsc [8] to 0, that is, to detect the disconnection signal falling from the pen tip # define wait4int (x) <8) | \ Users | users | s3c2410_adctsc_xp_sen | \ s3c2410_adctsc_xy_pst (3)/* adctsc register bits */# define s3c2410_adctsc_ym_sen (1 <7) # define S3C2410 _ Adctsc_yp_sen (1 <6) # define s3c2410_adctsc_xm_sen (1 <5) # define s3c2410_adctsc_xp_sen (1 <4) # define condition (1 <3) # define s3c2410_adctsc_auto_pst (1 <2) # define s3c2410_adctsc_xy_pst (x) & 0x3) <0) /* adccon register bits */# define partition (1 <15) # define s3c2410_adccon_prscen (1 <14) # define s3c2410_adccon_prscvl (x) & 0xff) <6) # define s3c2410_adccon_prscvlmask (0xff <6) # define s3c2410_adccon_selmux (x) & 0x7) <3) # define s3c2410_adccon_muxmask (0x7 <3) # define s3c2410_adccon_stdbm (1 <2) # define s3c2410_adccon_read_start (1 <1) # define partition (1 <0) # define s3c2410_adccon_startmask (0x3 <0) # ifdef s3c2410_adccon # UNDEF s3c2410_adccon # endif # ifdef s3c2410_adctsc # UNDEF s3c2410_adctsc # endif # ifdef s3c2410_adcdly # UNDEF s3c2410_adcdly # endif # ifdef s3c2410 _ Dcdat0 # UNDEF handler # endif # ifdef handler # UNDEF handler # endif # ifdef s3c2410_pa_adc # UNDEF s3c2410_pa_adc # endif # define s3c2410_pa_adc (0x58000000) Static void _ iomem * base_addr; # define s3c2410_adccon (base_addr + (0x00) # define s3c2410_adctsc (base_addr + (0x04) # define s3c2410_adcdly (base_addr + (0x08 )) # define s3c2410_adcdat0 (base_addr + (0x0c) # define s3c2410_adcdat1 (base_addr + (0x10) # ifdef config_pm # include <Linux/PM. h> # endif // drag is supported. // If drag is not supported, the pen stroke coordinates can be obtained, but the icons on the LCD do not respond. // You can see that the read interface is called, and the icon does not respond. # Define release // # definedebug # ifdef debug # define dprintkprintk # else # define dprintk # endiftypedef struct {unsigned short pressure; unsigned short X; unsigned short Y; unsigned short pad ;} ts_ret; typedef struct {int XScale; int xtrans; int yscale; int ytrans; int xyswap;} ts_cal; # define pen_up 0 # define pen_down1 # define pen_fleeting2 # define max_ts_buf16/* How many do we want to buffer */# UNDEF Use_async # define device_name "s3c2410-ts" # define tsraw_minor1typedef struct {unsigned int penstatus;/* pen_up, pen_down, pen_sample */ts_ret Buf [max_ts_buf]; /* Protect Against overrun */unsigned int head, tail;/* head and tail for queued events */wait_queue_head_t WQ; spinlock_t lock; # ifdef use_asyncstruct fasync_struct * AQ; # endif # ifdef config_pmstruct pm_dev * pm_dev; # endif} ts_dev; static ts_dev TSD Ev; # define buf_head (tsdev. buf [tsdev. head]) # define buf_tail (tsdev. buf [tsdev. tail]) # define incbuf (x, MoD) (++ (x) & (MOD)-1) Static int tsmajor = 0; static void (* tsevent) (void); # ifdef hook_for_drag # define ts_timer_delay (Hz/100)/* 10 MS */static struct timer_list ts_timer; # endif // pick-up regs Val from 2.4.18 & 2440 // ym_sen output drive enabled, XP pull enabled, normal ADC conversion, detect pen tip drop interrupt signal, waiting for interruption mode # define wait_down_int () _ raw_write L (0x000000d3, s3c2410_adctsc) // ym_sen output drive enabling, XP pull-up enabling, normal ADC conversion, detection pen tip lifting interrupt signal, waiting for interrupt mode # define wait_up_int () _ raw_writel (0x000001d3, s3c2410_adctsc) // xm_sen, xp_sen output drive enabled, XP pull disabled, normal ADC conversion, X Direction Measurement Mode # define mode_x_axis () _ raw_writel (0x00000069, s3c2410_adctsc) // equivalent to _ raw_writel (0x00000068, s3c2410_adctsc), that is, // xm_sen, yp_sen enabling, XP pulling prohibited, normal ADC conversion, no operation mode # define mode_x_axis_n () _ raw_writel (xp_extvlt | xm_gnd | yp_ain | ym _ Hiz | \ xp_pull_up_dis | xp_pst (nop_mode), s3c2410_adctsc) // ym_sen, yp_sen enabled, XP disabled, normal ADC conversion, y Direction Measurement Mode # define mode_y_axis () _ raw_writel (0x0000009a, s3c2410_adctsc) // _ raw_writel (0x00007ffa, s3c2410_adccon); -- A/D converter pre-divider enabling, pre-division value 0xff, simulate that the input channel sel_mux is XP and works in normal mode, enabling read start operations // _ raw_readl (s3c2410_adcdat0); -- read the value of adcdat # define start_adc_x () do {__ raw_writel (0x00007ffa, s3c2410_adccon); \__ raw_readl (s3c2410_adcd At0);} while (0) // how is the configuration the same as start_adc_x? Should it be 0x00007fea? # Define start_adc_y () Do {__ raw_writel (0x00007ffa, s3c2410_adccon); \__ raw_readl (s3c2410_adcdat1);} while (0) // prohibit read start operations, that is, read_start position 0 # define disable_ts_adc () _ raw_writel (_ raw_readl (s3c2410_adccon) & 0 xfffffffd, s3c2410_adccon) Static int adc_state = 0; static int X, Y; /* Touch Screen coorinates */# ifdef hook_for_drag # definert_bt_emu_tm (HZ> 1) + (HZ> 2) // 0.75 S // static 2010ts_r_x [5]; // static 2010ts_r _ Y [5]; // static services_r_idx; // static services_r_beg; static u32 dn_start; # endifstatic void tsevent_raw (void) {dprintk ("@ tvevent_raw () @ \ n"); If (tsdev. penstatus = pen_down) {// 2010i, J; # ifdef hook_for_drag latency = jiffies + ts_timer_delay; add_timer (& ts_timer); # Signature = x; buf_head.y = y; # ifdef hook_for_drag buf_head.pressure = (jiffies-dn_start)> = rt_bt_emu_tm)? Pen_fleeting: pen_down; # else buf_head.pressure = pen_down; # endif}/* If (tsdev. penstatus = pen_down) */else {# ifdef hook_for_drag del_timer (& ts_timer); # endifbuf_head.x = x; buf_head.y = y; buf_head.pressure = pen_up;} ts. head = incbuf (tsdev. head, max_ts_buf); dprintk ("@ wake_up_interruptible () in tvevent_raw () @ \ n "); wake_up_interruptible (& (tsdev. WQ); # ifdef use_asyncif (tsdev. AQ) Kill _ Fasync (& (tsdev. AQ), sigio, poll_in); # endif # ifdef config_pmpm_access (tsdev. pm_dev); # endif} static int tsread (ts_ret * ts_ret) {spin_lock_irq (& (tsdev. lock); ts_ret-> X = buf_tail.x; ts_ret-> Y = buf_tail.y; ts_ret-> pressure = buf_tail.pressure; tsdev. tail = incbuf (tsdev. tail, max_ts_buf); spin_unlock_irq (& (tsdev. lock); Return sizeof (ts_ret);} static ssize_t s3c2410_ts_read (struct file * filp, char * buffer, S Ize_t count, loff_t * PPOs) {ts_ret; retry: If (tsdev. Head! = Tsdev. tail) {int count; Count = tsread (& ts_ret); If (count) {printk ("@ ts_ret.x: % HD, ts_ret.y: % HD @ \ n ", ts_ret.x, ts_ret.y); copy_to_user (buffer, (char *) & ts_ret, count);} return count ;} else {If (filp-> f_flags & o_nonblock) Return-eagain; interruptible_sleep_on (& (tsdev. WQ); If (signal_pending (current) Return-erestartsys; goto retry;} return sizeof (ts_ret);} # ifdef use_asyncstatic int S3C2410 _ Ts_fasync (int fd, struct file * filp, int mode) {return fasync_helper (FD, filp, mode, & (tsdev. AQ) ;}# endifstatic unsigned int s3c2410_ts_poll (struct file * filp, struct poll_table_struct * Wait) {poll_wait (filp, & (tsdev. WQ), wait); Return (tsdev. head = tsdev. tail )? 0: (Pollin | pollrdnorm);} static inline void start_ts_adc (void) {adc_state = 0; mode_x_axis (); start_adc_x ();} static inline void s3c2410_get_xy (void) {If (adc_state = 0) {adc_state = 1; disable_ts_adc (); y = _ raw_readl (s3c2410_adcdat1) & 0x3ff; // X: f04 Y: f0e DH by PHT. mode_y_axis (); start_adc_y ();} else if (adc_state = 1) {adc_state = 0; disable_ts_adc (); X = _ raw_readl (s3c2410_adcdat0) & 0x3ff; // y: F 04 x: f0e DH by PHT. printk ("@ pen down: X: % d, Y: % d \ n", x, y); wait_up_int (); tsdev. penstatus = pen_down; tsevent () ;}} static irqreturn_t s3c2410_isr_adc (int irq, void * dev_id, struct pt_regs * REG) {dprintk ("@ s3c2410_isr_adc () @ \ n"); spin_lock_irq (& (tsdev. lock); If (tsdev. penstatus = pen_up) {dprintk ("@ s3c2410_isr_adc 1 @ \ n"); s3c2410_get_xy () ;}# ifdef hook_for_drage LSE {dprintk ("@ s3c2410_isr_adc 2 \ n"); s3c2410_get_xy () ;}# endifspin_unlock_irq (& (tsdev. lock); Return irq_handled;} static irqreturn_t s3c2410_isr_tc (int irq, void * dev_id, struct pt_regs * REG) {dprintk ("@ s3c2410_isr_tc () \ n "); spin_lock_irq (& (tsdev. lock); If (tsdev. penstatus = pen_up) {dprintk ("@ s3c2410_isr_tc 1 \ n"); # ifdef hook_for_drag dn_start = jiffies; // Add By gzliu # endif start_ts_adc ();} else {tsdev. penstatus = pen_up; dprintk ("@ s3c2410_isr_tc 2 \ n "); printk ("@ pen up: X: % d, Y: % d @ \ n", x, y ); wait_down_int (); tsevent ();} spin_unlock_irq (& (tsdev. lock); Return irq_handled;} # ifdef hook_for_dragstatic void ts_timer_handler (unsigned long data) {spin_lock_irq (& (tsdev. lock); If (tsdev. penstatus = pen_down) {start_ts_adc ();} s Pin_unlock_irq (& (tsdev. lock) ;}# endifstatic int s3c2410_ts_open (struct inode * inode, struct file * filp) {tsdev. head = tsdev. tail = 0; tsdev. penstatus = pen_up; # ifdef hook_for_drag init_timer (& ts_timer); ts_timer.function = ts_timer_handler; # endiftsevent = tsevent_raw; outputs (& (tsdev. WQ); // mod_inc_use_count; return 0;} static int s3c2410_ts_release (struct inode * inode, struct file * filp) {# I Fdef evaluate (& ts_timer); # endif // success; return 0;} static struct file_operations s3c2410_fops = {owner: this_module, open: s3c2410_ts_open, read: s3c2410_ts_read, release: success, # ifdef identifier: s3c2410_ts_fasync, # endifpoll: identifier,}; void tsevent_dummy (void) {}# ifdef config_pmstatic int identifier (struct pm_dev * pm_dev, pm_request_t req, void * Data) {Switch (req) {Case pm_suspend: tsevent = tsevent_dummy; break; Case pm_resume: tsevent = tsevent_raw; wait_down_int (); break;} return 0 ;} # endifstatic struct CLK * adc_clock; static int _ init s3c2410ts_probe (struct device * Dev) {int ret; tsevent = tsevent_dummy; dprintk ("@ s3c2410ts_probe @ \ n"); ret = register_chrdev (0, device_name, & s3c2410_fops); If (Ret <0) {printk (device_name "Can't get major number \ n"); return ret;} tsmajor = ret; adc_clock = clk_get (null, "ADC"); If (! Adc_clock) {printk (kern_err "failed to get ADC clock source \ n"); Return-enoent;} clk_use (adc_clock); clk_enable (adc_clock); base_addr = ioremap (callback, 0x20) ;__ raw_writel (wait4int (0), s3c2410_adctsc) ;__ raw_writel (30000, latency); // 30000 -- 20000ret = request_irq (irq_adc, s3c2410_isr_adc, temperature, device_name, s3c2410_isr_adc); If (RET) goto adc_failed; ret = request_irq (irq_tc, s3c241 0_isr_tc, sa_interrupt, device_name, s3c2410_isr_tc); If (RET) goto tc_failed;/* Wait for touch screen interrupts */wait_down_int "); values (mkdev (tsmajor, tsraw_minor), s_ifchr | s_irugo | s_iwusr, "touchscreen/% s", "0raw"); # endif # ifdef values = pm_register (values, pm_user_input, s3c2410_ts_pm_callback); # endifreturn 0; tc_fai Led: {printk (kern_err "TC failed !!!!!!!!!!!!! \ N "); free_irq (irq_adc, s3c2410_isr_adc);} adc_failed: {printk (kern_err" ADC failed !!!!!!!!!!!!! \ N "); return ret ;}} static struct device_driver s3c2410ts_driver = {. name = device_name ,. bus = & platform_bus_type ,. probe = s3c2410ts_probe, # ifdef config_pm.suspend = s3c2410ts_suspend ,. resume = s3c2410ts_resume, # endif}; static int _ init s3c2410ts_init (void) {int ret; printk ("@ s3c2410ts Init () @ \ n "); ret = driver_register (& s3c2410ts_driver); If (RET) {printk (" register % s driver failed, return code is % d \ n ", device_name, RET);} else {printk (" @ register % s driver success, return code is % d @ \ n ", device_name, RET);} return ret;} static void _ exit s3c2410ts_exit (void) {# ifdef config_devfs_fsdevfs_remove ("touchscreen/% d", 0); devfs_remove ("touchscreen"); # outputs (tsmajor, device_name); # ifdef config_pmpm_unregister (tsdev. pm_dev); # convert (irq_adc, short); free_irq (irq_tc, short); driver_unregister (& s3c2410ts_driver);} module_init (s3c2410ts_init); module_exit (s3c2410ts_exit );

Contact Us

The content source of this page is from Internet, which doesn't represent Alibaba Cloud's opinion; products and services mentioned on that page don't have any relationship with Alibaba Cloud. If the content of the page makes you feel confusing, please write us an email, we will handle the problem within 5 days after receiving your email.

If you find any instances of plagiarism from the community, please send an email to: info-contact@alibabacloud.com and provide relevant evidence. A staff member will contact you within 5 working days.

A Free Trial That Lets You Build Big!

Start building with 50+ products and up to 12 months usage for Elastic Compute Service

  • Sales Support

    1 on 1 presale consultation

  • After-Sales Support

    24/7 Technical Support 6 Free Tickets per Quarter Faster Response

  • Alibaba Cloud offers highly flexible support services tailored to meet your exact needs.