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
