Hi,

I have a DM6446 EVM and I want to add TSC2007 touchscreen driver to SDK2.0
(2.6.18_mvl5).

There is a function name "gpio_to_irq"  which adds DAVINCI_N_AINTC_IRQ (64)
to gpio number (6) but result is not the same irq line number for GPIO6
IRQ_GPIO6 (54) writen in irqs.h. (64+6 = 54 ??). Why does it so?? I prefer
54 and it works with some errors:

1-) When I run the below commands

>insmod tsdev.ko
ts: Compaq touchscreen protocol output
>insmod 
>tsc2007<http://focus-webapps.ti.com/general/docs/sitesearch/searchdevice.tsp?partNumber=tsc2007>
.ko
input:  
TSC2007<http://focus-webapps.ti.com/general/docs/sitesearch/searchdevice.tsp?partNumber=tsc2007>as
/class/input/input0
No IRQF_TRIGGER set_type function for IRQ 54 (AINTC)

There is an error  "No IRQF_TRIGGER set_type function for IRQ 54 (AINTC)" .
What does it mean?

2-) When I touch my screen there is an another error shown below and after
some time linux crashes.
BUG: scheduling while atomic: swapper/0x00000103/0, CPU#0
BUG: scheduling while atomic: swapper/0x00000103/0, CPU#0
BUG: scheduling while atomic: swapper/0x00000103/0, CPU#0
BUG: scheduling while atomic: swapper/0x00000103/0, CPU#0

Below is the 
tsc2007<http://focus-webapps.ti.com/general/docs/sitesearch/searchdevice.tsp?partNumber=tsc2007>touchscreen
driver:

***********************************************GPIO_TO_IRQ****************************************************************************

static inline int gpio_to_irq(unsigned gpio
{
 return DAVINCI_N_AINTC_IRQ + gpio;
}

*******************************************************************************************************************************************



*******************************************************************************************************************************************

/* *
 * tsc2007_core.c
 * Driver for Texas Instruments
TSC2007<http://focus-webapps.ti.com/general/docs/sitesearch/searchdevice.tsp?partNumber=tsc2007>touchscreen
 * controller on I2C bus on AT91SAM9261 board.
 *
 * Author: Joseph Robert  ([email protected])
 * Date:   12-06-2008
 * */


#include <linux/init.h>
#include <linux/err.h>
#include <linux/input.h>
#include <linux/delay.h>
#include <linux/interrupt.h>
#include <linux/slab.h>
#include <linux/i2c.h>
#include <linux/byteorder/generic.h>
#include <linux/timer.h>
#include <linux/jiffies.h>
#include 
"tsc2007<http://focus-webapps.ti.com/general/docs/sitesearch/searchdevice.tsp?partNumber=tsc2007>
.h"
#include <asm/arch-davinci/gpio.h>  //touch by ferhat_olgun
#include <asm/mach-types.h> //touch by ferhat_olgun
#include <linux/irq.h>  //touch by ferhat_olgun


int pen_down_state (unsigned int pin)
{
 pin;
 return !gpio_get_value(6);
 }

int tsc2007_detect_penirq (void)
{
 u32 gpio = 6;

 gpio_direction_input(GPIO(6));
  set_irq_type(gpio_to_irq(gpio), IRQT_FALLING);
  return 54; //GPIO(6);
}



static unsigned int short normal_i2c[] = { 0x48, I2C_CLIENT_END };

I2C_CLIENT_INSMOD_1
(tsc2007<http://focus-webapps.ti.com/general/docs/sitesearch/searchdevice.tsp?partNumber=tsc2007>
);

static struct i2c_driver tsc2007_driver = {
 .driver = {
  .owner = THIS_MODULE,
  .name = 
"tsc2007<http://focus-webapps.ti.com/general/docs/sitesearch/searchdevice.tsp?partNumber=tsc2007>
",
 },

 .attach_adapter = tsc2007_attach,
 .detach_client = tsc2007_detach,
};

/* driver data structure */

struct tsc2007_data
{
 struct i2c_client client;
 struct timer_list timer;
 struct input_dev *idev;
 unsigned int pen_irq;
 enum power_down_mode pd;
 enum resolution_mode m;
};


/*
 *  Function to initialize the Power down mode & resolution modes.
 *  The required configuration values must be set up here by
 *  initializing the structure data using appropriate enums.
 *
 *  Parameters:
 *       input:
 *  client: The i2c_client device for our chip
 */

static void tsc2007_init_client (struct i2c_client *client)
{
 struct tsc2007_data *data = i2c_get_clientdata (client);
 data->pd = PD_POWERDOWN_ENABLEPENIRQ;

#ifdef BIT_MODE_12
 data->m = M_12BIT;
#else
 data->m = M_8BIT;
#endif
 return;
}

/*  Funtion to issue and read the results for all the commands except the
setup
 *  command
 *
 *  Parameters:
 *  input: data: struct tsc2007_data structure
 *  cmd  : enum converer_function to select the function of the controller.
 *
 *     output:
 *  value: The result of the corresponding measurement based on the command
byte sent.
 */

static int tsc2007_read (struct tsc2007_data *data, enum converter_function
cmd)
{
 u8 command_byte;
 u16 value = 0;
 u32 stat = 0;
 struct i2c_client *new_client = &data->client;

 /* Command byte to be sent based on the structure data values */

 command_byte = TSC2007_CMD (cmd, data->pd, data->m);
 stat = i2c_master_send (new_client, &command_byte, BYTES_TO_TX);
 if (stat != BYTES_TO_TX)
  alert_tsc ("unable to send %#x command: %s\n",
    command_byte, __FUNCTION__);

 /* Receive 2 bytes of data for 12 bit mode and 1 byte for 8 bit mode */

 stat = i2c_master_recv (new_client, (u8 *) & value, BYTES_TO_RX);
 if (stat != BYTES_TO_RX)
  alert_tsc ("unable to receive data: %s\n", __FUNCTION__);
 return value;
}

/*  Timer function called whenever the touch is detected.This function is
used
 *  to read the X and Y coordinates and also the Z1,Z2 values if Actual
pressure
 *  is to be reported. Pen down values are reported to the subsystem until
 *  the pen is down & returns by enbling IRQ on pen up.
 *  parameters:
 *       input:
 *  arg: struct tsc2007_data structure
 */

static void tsc2007_timer (unsigned long arg)
{
 struct tsc2007_data *data = (struct tsc2007_data *) arg;
 struct i2c_client *client = &data->client;
 u8 measure_x =
  TSC2007_CMD (MEAS_XPOS, data->pd, data->m);
 u8 measure_y =
  TSC2007_CMD (MEAS_YPOS, data->pd, data->m);
 u16 x_value = 0;
 u16 y_value = 0;
 s32 stat = 0;
 u16 kernel_x = 0;
 u16 kernel_y = 0;
 u32 pressure_val = 0;
#ifdef REPORT_ACTUAL_PRESSURE
 u16 z1_value = 0;
 u16 z2_value = 0;
 u16 kernel_z1 = 0;
 u16 kernel_z2 = 0;
 u8 measure_z1 =
  TSC2007_CMD (MEAS_Z1, data->pd, data->m);
 u8 measure_z2 =
  TSC2007_CMD (MEAS_Z2, data->pd, data->m);
#endif

 /* Try to read Y values */

 stat = i2c_master_send (client, &measure_y, BYTES_TO_TX);
 if (unlikely (stat != BYTES_TO_TX))
  alert_tsc ( "unable to send Y read command: %s\n", __FUNCTION__);
 stat = i2c_master_recv (client,(u8*)&y_value, BYTES_TO_RX);
 if (unlikely (stat != BYTES_TO_RX))
  alert_tsc ("unable to receive data: %s\n", __FUNCTION__);


 /*Try to read the X values */

 stat = i2c_master_send (client, &measure_x, BYTES_TO_TX);
 if (unlikely (stat != BYTES_TO_TX))
  alert_tsc ("unable to send X read command: %s\n", __FUNCTION__);
 stat = i2c_master_recv (client,(u8*)&x_value, BYTES_TO_RX);
 if (unlikely (stat != BYTES_TO_RX))
  alert_tsc ("unable to receive data: %s\n", __FUNCTION__);

 /**
  * The values coming out of the
TSC2007<http://focus-webapps.ti.com/general/docs/sitesearch/searchdevice.tsp?partNumber=tsc2007>are
in big-endian format and
  * ****NEED BYTE SWAPPING***** on little endian machines. Depending upon
  * the resolution mode used proper bits have to be masked off before the
  * values can be used.
  * */

 if (data->m == M_12BIT)
 {

  /* Bit masking and data alignment for 12 bit mode */

  kernel_y = (((be16_to_cpu (y_value)) >> 4) & VALUE_MASK);
  kernel_x = (((be16_to_cpu (x_value)) >> 4) & VALUE_MASK);
 }

 /* No need of bit masking in case of 8 bit mode */

 else if (data->m == M_8BIT)
 {
  kernel_y = y_value;
  kernel_x = x_value;
 }

 /*  To Report constant pressure value in the range 1-15000
  *  (MAX pressure recevied as per Platform data. 7500 is chosen
  *  as an intermediate value in that range
  */

 pressure_val = FIXED_PRESSURE_VAL;

 /*  Measuring touch pressure can also be done with the
TSC2007<http://focus-webapps.ti.com/general/docs/sitesearch/searchdevice.tsp?partNumber=tsc2007>
.
  *  To determine pen touch, the pressure of the touch must
  *  be determined
  */

#ifdef REPORT_ACTUAL_PRESSURE

 /* Try to read Z1 values */
 stat = i2c_master_send (client, &measure_z1, BYTES_TO_TX);
 if (unlikely (stat != BYTES_TO_TX))
  alert_tsc ("unable to send Y read command: %s\n", __FUNCTION__);
 stat = i2c_master_recv (client,(u8*)&z1_value, BYTES_TO_RX);
 if (unlikely (stat != BYTES_TO_RX))
  alert_tsc ("unable to receive data: %s\n", __FUNCTION__);


 /*Try to read the Z2 values */
 stat = i2c_master_send (client, &measure_z2, BYTES_TO_TX);
 if (unlikely (stat != BYTES_TO_TX))
  alert_tsc ("unable to send X read command: %s\n", __FUNCTION__);
 stat = i2c_master_recv (client,(u8*)&z2_value, BYTES_TO_RX);
 if (unlikely (stat != BYTES_TO_RX))
  alert_tsc ("unable to receive data: %s\n", __FUNCTION__);


 /* Bit masking and data alignment for 12 bit mode */

 if (data->m == M_12BIT)
 {
  kernel_z1 = (((be16_to_cpu (z1_value)) >> 4) & VALUE_MASK);
  kernel_z2 = (((be16_to_cpu (z2_value)) >> 4) & VALUE_MASK);
 }

 /* No need of bit masking in case of 8 bit mode */

 else if (data->m == M_8BIT)
 {
  kernel_z1 = z1_value;
  kernel_z2 = z2_value;
 }

 /* Actual pressure calculation using the formula to calculate Rtouch.
    The pressure is not reported if in case z1=0 */

 if (z1_value)
 {
  pressure_val =((kernel_z2 / kernel_z1 - 1) *
    RX_PLATE_VAL * kernel_x) / ADC_MAX;
  pressure_val = pressure_val & VALUE_MASK ;
 }
#endif


 /* Check for prolonged touches i.e drags and drawings.
  * If pen is still down restart the timer else report pen up and return
  */


 if (pen_down_state (data->pen_irq))
 {
  /*Reporting to input sub system */
  input_report_abs (data->idev, ABS_X,
    (ADC_MAX - kernel_y)* CONFIG_INPUT_MOUSEDEV_SCREEN_X / ADC_MAX);
  input_report_abs (data->idev, ABS_Y,
    kernel_x *CONFIG_INPUT_MOUSEDEV_SCREEN_Y / ADC_MAX);
  input_report_abs (data->idev, ABS_PRESSURE, pressure_val);
  input_report_key (data->idev, BTN_TOUCH, TOUCH_TRUE);
  input_sync (data->idev);
  mod_timer (&data->timer, jiffies + START_TIMER_DELAY);
 }
 else
 {
  input_report_key (data->idev, BTN_TOUCH, TOUCH_FALSE);
  input_report_abs (data->idev, ABS_PRESSURE, PRESSURE_FALSE);
  input_sync (data->idev);
  enable_irq (data->pen_irq);
 }
 return;

}

/*  IRQ handler function for penirq.The timer function is called here on pen
 *  down and also the pen up is reported here to the input subsystem.
 *  parameters:
 *  input:
 *  irq: irq number
 *   v: struct tsc2007_data structure
 *
 * output:
 *  IRQ HANDLED status
 */

static irqreturn_t tsc2007_handle_penirq (int irq, void *v ,struct pt_regs
*regs)  //touch by ferhat_olgun
{
 struct tsc2007_data *data = (struct tsc2007_data *) v;

 disable_irq (data->pen_irq);

 /* Start timer if touch is detected (pen down) */

 if ( pen_down_state (data->pen_irq))
 {
  mod_timer (&data->timer, jiffies + START_TIMER_DELAY);
 }
 else
 {
  enable_irq (data->pen_irq);
 }
 return IRQ_HANDLED;
}

/* *
 * Register the the
TSC2007<http://focus-webapps.ti.com/general/docs/sitesearch/searchdevice.tsp?partNumber=tsc2007>to
the kernel. Allocate a input device,
 * request IRQs and register.
 * parameters:
 * input:
 *  data: tsc2007_data structure
 * output:
 *  function exit status
 *
 * */

static int tsc2007_register_driver (struct tsc2007_data *data)
{
 struct input_dev *idev;

 int ret;
 data->pen_irq = tsc2007_detect_penirq ();

 init_timer (&data->timer);
 data->timer.function = &tsc2007_timer;
 data->timer.data = (unsigned int) (&data->client);

 idev = input_allocate_device ();

 if (idev == NULL)
 {
  alert_tsc ("Unable to allocate input device\n");
  return -ENOMEM;
 }

 idev->name = DRIVER_NAME;
 idev->private = data;
 //idev->dev.parent = &((data->client).dev);
 idev->cdev.dev = &((data->client).dev); // touch by ferhat_olgun

/*
 idev->evbit[0] = BIT_MASK (EV_ABS) | BIT_MASK (EV_KEY);
 idev->keybit[BIT_WORD (BTN_TOUCH)] = BIT_MASK (BTN_TOUCH);
 idev->absbit[BIT_WORD (ABS_X)] = BIT_MASK (ABS_X);
 idev->absbit[BIT_WORD (ABS_Y)] = BIT_MASK (ABS_Y);
 idev->absbit[BIT_WORD (ABS_PRESSURE)] = BIT_MASK (ABS_PRESSURE);
*/
 idev->evbit[0] = BIT (EV_ABS) | BIT (EV_KEY);
 idev->keybit[LONG (BTN_TOUCH)] = BIT (BTN_TOUCH);
 idev->absbit[LONG (ABS_X)] = BIT (ABS_X);
 idev->absbit[LONG (ABS_Y)] = BIT (ABS_Y);
 idev->absbit[LONG (ABS_PRESSURE)] = BIT (ABS_PRESSURE);



 /* Informing the input subsystem the range of values that our controller
  * can send.
  */

 input_set_abs_params (idev, ABS_X, 0, ADC_MAX, 0, 0);
 input_set_abs_params (idev, ABS_Y, 0, ADC_MAX, 0, 0);
 input_set_abs_params (idev, ABS_PRESSURE, 0, ADC_PRESSURE_MAX, 0, 0);

 data->idev = idev;

 dbg_tsc 
("tsc2007<http://focus-webapps.ti.com/general/docs/sitesearch/searchdevice.tsp?partNumber=tsc2007>:
registering input device\n");
 if (input_register_device (data->idev) != 0)
 {
  alert_tsc ("Unable to register input device: %s", __FUNCTION__);
  goto err_exit;
 }

 ret = request_irq (data->pen_irq, tsc2007_handle_penirq,
   IRQF_TRIGGER_FALLING, DRIVER_NAME, data); // IRQF_TRIGGER_FALLING touch
by ferhat_olgun

 if (ret != 0)
 {
  alert_tsc ("Unable to grab IRQ\n");
  goto err_exit;
 }
 return 0;

err_exit:
 return -ENODEV;
}

/*   I2C detect function is used to populate the client data ,probe the I2C
 *   device by sending a command and receiving an ack.Setup command is sent
 *   to configure the Rirq value and enable/use MAV filter.Attach the Device
 *   to the I2C bus and also to validate all the commands of the
tsc2007<http://focus-webapps.ti.com/general/docs/sitesearch/searchdevice.tsp?partNumber=tsc2007>
 *   controller.
 *
 *   parameters:
 *      input:
 *       adapter: Global structure adapter (defined in linux/i2c.h),
 *       address: i2c address,
 *       kind   : kind of probing (forceful detection in this case).
 *       output:
 *        function exit status
 *
 */

static int tsc2007_detect (struct i2c_adapter *adapter, int address, int
kind)
{
 struct i2c_client *new_client;
 struct tsc2007_data *data;
 s32 err = 0;
 char *name = 
"tsc2007<http://focus-webapps.ti.com/general/docs/sitesearch/searchdevice.tsp?partNumber=tsc2007>
";
 u8 command_byte=0;

 /* Check if the I2C Master supports the following functionalities*/

 if (!i2c_check_functionality (adapter, I2C_FUNC_SMBUS_BYTE_DATA
    | I2C_FUNC_I2C | I2C_FUNC_SMBUS_WORD_DATA))
 {
  alert_tsc ("I2C Functionality not supported\n");
  goto exit;
 }

 data = kcalloc (1, sizeof (*data), GFP_KERNEL);

 if (NULL == data)
 {
  err = -ENOMEM;
  goto exit;
 }

 new_client = &data->client;
 i2c_set_clientdata (new_client, data);
 new_client->addr = address;
 new_client->adapter = adapter;
 new_client->driver = &tsc2007_driver;
 new_client->flags = 0;
 strlcpy (new_client->name, name, I2C_NAME_SIZE);

 /* Function to initialize the structure data */

 tsc2007_init_client (new_client);

 /*Try probing...... Send some command and wait for the ACK.If we have an
   ack assume that its our device */

 dbg_tsc ("%s: probing address: %#x\n", __FUNCTION__, address);
 command_byte = TSC2007_CMD (MEAS_TEMP0, data->pd, data->m);

 if ((BYTES_TO_TX !=
    i2c_master_send (new_client, &command_byte, BYTES_TO_TX)))
 {
  alert_tsc ("%s\n", "Unable to probe a
TSC2007<http://focus-webapps.ti.com/general/docs/sitesearch/searchdevice.tsp?partNumber=tsc2007>device
on I2C bus");
  goto err_exit;
 }

 /*Device found. Attach it to the I2C bus */

 dbg_tsc ("%s: attaching a
tsc2007<http://focus-webapps.ti.com/general/docs/sitesearch/searchdevice.tsp?partNumber=tsc2007>device
on : %#x\n",
   __FUNCTION__, address);
 if ( i2c_attach_client (new_client))
 {
  alert_tsc ("%s: unable to attach device on : %#x\n",
    __FUNCTION__, address);
  goto err_exit;
 }

 /*SET UP COMMAND */

#ifdef SETUP_MAV_RIRQ
 command_byte =(u8) CURRENT_SETUP_SETTING;
 err = i2c_master_send (new_client, &command_byte, BYTES_TO_TX);
 dbg_tsc("Setup Command 0x%x:%d\n", command_byte, err);


 /*  NOTE: Setup command has no ack and hence an error message
  *  (i2c-adapter i2c-0: sendbytes: error - bailout) appears when
  *  the module is inserted with the SETUP_MAV_RIRQ
  *  MACRO defined.
  */

#endif

 /* Option of validating all the commands of
tsc2007<http://focus-webapps.ti.com/general/docs/sitesearch/searchdevice.tsp?partNumber=tsc2007>controller
*/

#ifdef VALIDATE_ALL_COMMANDS
 dbg_tsc ("TEMP0 = %#x\n", tsc2007_read (data, MEAS_TEMP0));
 dbg_tsc ("AUX0 = %#x\n", tsc2007_read (data, MEAS_AUX));
 dbg_tsc ("TEMP1 = %#x\n", tsc2007_read (data, MEAS_TEMP1));
 dbg_tsc ("XPOS = %#x\n", tsc2007_read (data, MEAS_XPOS));
 dbg_tsc ("YPOS = %#x\n", tsc2007_read (data, MEAS_YPOS));
 dbg_tsc ("ACTIVATED X DRIVERS = %#x\n",
   tsc2007_read (data, ACTIVATE_X_DRIVERS));
 dbg_tsc ("ACTIVATED Y DRIVERS = %#x\n",
   tsc2007_read (data, ACTIVATE_Y_DRIVERS));
 dbg_tsc ("ACTIVATED YnX DRIVERS = %#x\n",
   tsc2007_read (data, ACTIVATE_YnX_DRIVERS));
 dbg_tsc ("PRESSURE Z1 = %#x\n", tsc2007_read (data, MEAS_Z1));
 dbg_tsc ("PRESSURE Z2 = %#x\n", tsc2007_read (data, MEAS_Z2));
#endif
 err = tsc2007_register_driver (data);

 if (err != 0)
  goto err_exit;

exit:return 0;

err_exit:
     return -ENODEV;
}

/* Function to attach the i2c_client
 *
 * parameters:
 *  input:
 *   adapter: The global adapter structure (defined in linux\i2c.h)
 *
 * */

static int tsc2007_attach (struct i2c_adapter *adapter)
{
 return i2c_probe (adapter, &addr_data, &tsc2007_detect);
}

/*Function to detach the i2c_client
 *
 * parameters:
 *     output:
 *       client: The i2c client device for our chip
 *
 * */

static int tsc2007_detach (struct i2c_client *client)
{
 int err = 0;
 struct tsc2007_data *data = i2c_get_clientdata (client);
 input_unregister_device (data->idev);
 input_free_device (data->idev);
 free_irq (data->pen_irq, data);
 del_timer_sync (&data->timer);
 if ((err = i2c_detach_client (client)))
 {
  alert_tsc ("Device unregistration failed\n");
  return err;
 }
 return err;
}

/* Init function of the driver called during module inserion */

int __init tsc2007_init (void)
{
 printk(KERN_INFO "tsc2007_init \n");
 return i2c_add_driver (&tsc2007_driver);
}

/* EXit function of the driver called during module removal */

void __exit tsc2007_exit (void)
{
 i2c_del_driver (&tsc2007_driver);
}

module_init (tsc2007_init);
module_exit (tsc2007_exit);

MODULE_DESCRIPTION("TSC2007<http://focus-webapps.ti.com/general/docs/sitesearch/searchdevice.tsp?partNumber=tsc2007>TouchScreen
Driver");
MODULE_LICENSE ("GPL");
MODULE_AUTHOR ("Joseph Robert:report bugs to [email protected]");
_______________________________________________
Davinci-linux-open-source mailing list
[email protected]
http://linux.davincidsp.com/mailman/listinfo/davinci-linux-open-source

Reply via email to