Linux-powered touch screen drivers

Source: Internet
Author: User

The touch screen is summed up as input subsystem, here is mainly for the resistive screen, the use of the process is as follows: When the touch pen is pressed, resulting in an interrupt. Start the ADC conversion x, y coordinates in the interrupt handler function handler. The ADC is terminated, an ADC interrupt is generated, a timer is escalated in the ADC interrupt handler function (input_event), the timer is activated again (can handle sliding, long press), and the button is released.
The wording of the driver is basically the same as the writing input subsystem. Write the entry function, export function and modify, add the relevant header file, and then start to refine the functions, in the entry function to allocate INPUT_DEV structure, set (what kind of events can be generated, which can produce such events), registration equipment, hardware-related operations. The export function mainly releases some resources that were previously registered and allocated. The relevant registers should also be set according to the actual needs based on the 2440 Data sheet ADC conversion and touch screen chapter.

#include <linux/errno.h>

#include <linux/kernel.h>
#include <linux/module.h>
#include <linux/slab.h>
#include <linux/input.h>
#include <linux/init.h>
#include <linux/serio.h>
#include <linux/delay.h>
#include <linux/platform_device.h>
#include <linux/clk.h>
#include <asm/io.h>
#include <asm/irq.h>

#include <asm/plat-s3c24xx/ts.h>

#include <asm/arch/regs-adc.h>
#include <asm/arch/regs-gpio.h>

struct S3c_ts_regs {
unsigned long Adccon;
unsigned long ADCTSC;
unsigned long adcdly;
unsigned long adcdat0;
unsigned long adcdat1;
unsigned long ADCUPDN;
}; Register controller Structure Body

static struct Input_dev *s3c_ts_dev;
Static volatile struct S3c_ts_regs *s3c_ts_regs;

static struct timer_list Ts_timer;

static void Enter_wait_pen_down_mode (void)//Enter to wait for touch pen to press mode
{
S3C_TS_REGS->ADCTSC = 0xd3; Enter the wait break mode Bit[8] is 0 2440 manual P442
}

static void Enter_wait_pen_up_mode (void)//Enter to wait for touch pen to release mode
{
S3C_TS_REGS->ADCTSC = 0x1d3; /* Enter the wait interrupt mode bit[8] 1 2440 manual P442 */
}

static void Enter_measure_xy_mode (void)/* Enters XY measurement mode */
{
S3C_TS_REGS->ADCTSC = (1<<3) | (1<<2);
}

static void Start_adc (void)
{
S3c_ts_regs->adccon |= (1<<0); /* Start ADC */
}

static int s3c_filter_ts (int x[], int y[])/* Software filter */
{
#define ERR_LIMIT 10/* Experience value, tolerance value */

int avr_x, avr_y;
int det_x, det_y;

avr_x = (X[0] + x[1])/2;
Avr_y = (Y[0] + y[1])/2;

det_x = (x[2] > avr_x)? (X[2]-avr_x): (Avr_x-x[2]);
Det_y = (y[2] > avr_y)? (Y[2]-avr_y): (Avr_y-y[2]);

if ((det_x > Err_limit) | | (Det_y > Err_limit))
return 0;

avr_x = (X[1] + x[2])/2;
Avr_y = (Y[1] + y[2])/2;

det_x = (X[3] > avr_x)? (X[3]-avr_x): (Avr_x-x[3]);
Det_y = (Y[3] > avr_y)? (Y[3]-avr_y): (Avr_y-y[3]);

if ((det_x > Err_limit) | | (Det_y > Err_limit))
return 0;

return 1;
}

static void S3c_ts_timer_function (unsigned Long data)
{
if (S3c_ts_regs->adcdat0 & (1<<15))//* Assume time to */
{
/* Already released */
Input_report_abs (S3c_ts_dev, abs_pressure, 0); /* Escalation event with a pressure value of 0 */
Input_report_key (S3c_ts_dev, Btn_touch, 0);
Input_sync (S3c_ts_dev); /* Synchronize after reporting */
Enter_wait_pen_down_mode (); /* Enter touch-wait mode */
}
Else
{
/* measure x/y coordinates */
Enter_measure_xy_mode ();
START_ADC ();
}
}


static irqreturn_t Pen_down_up_irq (int irq, void *dev_id)
{
if (S3c_ts_regs->adcdat0 & (1<<15))/* 2440 manual P447 ADCDAT0 Register */
{
PRINTK ("pen up\n");
Input_report_abs (S3c_ts_dev, abs_pressure, 0);
Input_report_key (S3c_ts_dev, Btn_touch, 0);
Input_sync (S3c_ts_dev);
Enter_wait_pen_down_mode ();
}
Else
{
PRINTK ("pen down\n");
Enter_wait_pen_up_mode ();
Enter_measure_xy_mode ();
START_ADC ();
}
return irq_handled;
}

static irqreturn_t Adc_irq (int irq, void *dev_id)
{
static int cnt = 0;
static int x[4], y[4];
int Adcdat0, ADCDAT1;


/* Optimization Action 2: Discard this result if the stylus is found to be released when the ADC is complete */
Adcdat0 = s3c_ts_regs->adcdat0;
ADCDAT1 = s3c_ts_regs->adcdat1;

If (S3c_ts_regs->adcdat0 & (1<<15))
{
/* has been released */
CNT = 0;
Input_report_abs (S3c_ts_dev, abs_pressure, 0);
Input_report_key (S3c_ts_dev, Btn_touch, 0);
Input_sync (S3c_ts_dev);    
Enter_wait_pen_down_mode (); /*  after the measurement to enter the wait to release mode, so as to continuous operation  */
}
Else
{
//PRINTK ("Adc_irq cnt =%d, x =%d, y =%d\n", ++cnt, Adcdat0 & 0x3ff, ADCDAT1 & 0X3FF);
/* Optimization measures 3: Multiple measurements averaging */
x[cnt] = adcdat0 & 0x3ff;
Y[CNT] = adcdat1 & 0x3ff;
++cnt;
if (cnt = = 4)
{
/* optimization measures 4: Software filtering */
if (s3c_filter_ts (x, y))
{
//PRINTK ("x =%d, y =%d\n", (x[0]+x[1]+x[ 2]+X[3])/4, (Y[0]+y[1]+y[2]+y[3])/4);
Input_report_abs (S3c_ts_dev, Abs_x, (X[0]+x[1]+x[2]+x[3])/4);
Input_report_abs (S3c_ts_dev, Abs_y, (Y[0]+y[1]+y[2]+y[3])/4);
Input_report_abs (S3c_ts_dev, abs_pressure, 1);
Input_report_key (S3c_ts_dev, Btn_touch, 1);
Input_sync (S3c_ts_dev);
}
cnt = 0;
Enter_wait_pen_up_mode ();

/* Start timer handle long Press/slide */
Mod_timer (&ts_timer, jiffies + hz/100);
}
Else
{
Enter_measure_xy_mode ();
START_ADC ();
}
}

return irq_handled;
}

static int s3c_ts_init (void)
{
struct clk* CLK;

/* 1. Assign a input_dev struct */
S3c_ts_dev = Input_allocate_device ();

/* 2. Set */
/* 2.1 What kind of event can be generated */
Set_bit (Ev_key, s3c_ts_dev->evbit);
Set_bit (Ev_abs, s3c_ts_dev->evbit);

/* 2.2 can generate events in this type of event */
Set_bit (Btn_touch, s3c_ts_dev->keybit);

Input_set_abs_params (S3c_ts_dev, abs_x, 0, 0x3ff, 0, 0);
Input_set_abs_params (S3c_ts_dev, abs_y, 0, 0x3ff, 0, 0);
Input_set_abs_params (S3c_ts_dev, abs_pressure, 0, 1, 0, 0);


/* 3. Register */
Input_register_device (S3c_ts_dev);

/* 4. Hardware-related Operations */
/* 4.1 Enable clock (clkcon[15]) */
CLK = Clk_get (NULL, "ADC");
Clk_enable (CLK);

/* 4.2 Set S3C2440 's adc/ts register */
S3c_ts_regs = Ioremap (0x58000000, sizeof (struct s3c_ts_regs));

/* BIT[14]: 1-a/d converter Prescaler Enable
* Bit[13:6]: A/D converter prescaler value,
* adcclk=pclk/(49+1) =50mhz/(49+1) =1mhz
* Bit[0]: A/D conversion starts by enable. First set to 0
*/
S3c_ts_regs->adccon = (1<<14) | (49<<6);

REQUEST_IRQ (IRQ_TC, PEN_DOWN_UP_IRQ, Irqf_sample_random, "Ts_pen", NULL);
REQUEST_IRQ (IRQ_ADC, ADC_IRQ, Irqf_sample_random, "ADC", NULL);

/* Optimization measures 1:
* Set the adcdly to the maximum value, which causes the voltage to stabilize before issuing the IRQ_TC interrupt
*/
s3c_ts_regs->adcdly = 0xFFFF;

/* Optimization Action 5: Use timer to handle long press, slide case
*
*/
Init_timer (&ts_timer);
Ts_timer.function = s3c_ts_timer_function;
Add_timer (&ts_timer);

Enter_wait_pen_down_mode ();

return 0;
}

static void S3c_ts_exit (void)
{
FREE_IRQ (IRQ_TC, NULL);
FREE_IRQ (IRQ_ADC, NULL);
Iounmap (S3c_ts_regs);
Input_unregister_device (S3c_ts_dev);
Input_free_device (S3c_ts_dev);
Del_timer (&ts_timer);
}

Module_init (S3c_ts_init);
Module_exit (S3c_ts_exit);


Module_license ("GPL");

Linux-powered touch screen drivers

Related Article

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.