📄 hx4700_ts.c
字号:
ts->input->absmax[ABS_X] = 32767; ts->input->absmin[ABS_Y] = 0; ts->input->absmax[ABS_Y] = 32767; ts->input->absmin[ABS_PRESSURE] = 0; ts->input->absmax[ABS_PRESSURE] = 1; ts->input->keybit[LONG(_KEY_RECORD)] |= BIT(_KEY_RECORD); /* record */ ts->input->keybit[LONG(_KEY_CALENDAR)] |= BIT(_KEY_CALENDAR); /* calendar */ ts->input->keybit[LONG(_KEY_HOMEPAGE)] |= BIT(_KEY_HOMEPAGE); ts->input->name = "hx4700_ts"; ts->input->private = ts; input_register_device(ts->input); ts->timer.function = ts_timer_callback; ts->timer.data = (unsigned long)ts; ts->state = STATE_WAIT_FOR_TOUCH; init_timer (&ts->timer); INIT_WORK(&serial_work, start_read, ts); dev_set_drvdata(dev, ts); /* *** Initialize the SSP interface *** */ ssp_init(); down(&serial_mutex); /* Make sure the device is in such a state that it can give pen * interrupts. */ while(!(SSSR_P2 & (1 << 2))) ; SSDR_P2 = 0xd00000; for(retval = 0; retval < 100; retval++) { if(SSSR_P2 & (1 << 3)) { while(SSSR_P2 & (1 << 3)) { (void)SSDR_P2; } break; } mdelay(1); } up(&serial_mutex); ts->irq = HX4700_IRQ( TOUCHPANEL_IRQ_N ); retval = request_irq(ts->irq, pen_isr, SA_INTERRUPT, "hx4700_ts", ts); if(retval) { printk("Unable to get interrupt\n"); input_unregister_device (ts->input); return -ENODEV; } set_irq_type(ts->irq, IRQT_FALLING); /* *** Initialize the ASIC3 key interrupts *** */ /* Maybe shouldn't do this here, but take advantage of input * device already configured */ asic3_key[0].gpiod_val = GPIOD_KEY_AP2_N; asic3_key[0].gpiod_bit = (1<<GPIOD_KEY_AP2_N); asic3_key[0].rising = 0; asic3_key[0].key = _KEY_CALENDAR; irq = asic3_irq_base( &hx4700_asic3.dev ) + ASIC3_GPIOD_IRQ_BASE + GPIOD_KEY_AP2_N; err = request_irq( irq, key_isr, SA_INTERRUPT, "HX4700 AP2 Key", (void *)&asic3_key[0] ); if (err) { printk(KERN_ERR "GPIOD_KEY_AP2_N: can't request IRQ\n"); } else { set_irq_type( irq, IRQT_FALLING ); asic3_key[0].irq = irq; } asic3_key[1].gpiod_val = GPIOD_KEY_AP4_N; asic3_key[1].gpiod_bit = (1<<GPIOD_KEY_AP4_N); asic3_key[1].rising = 0; asic3_key[1].key = _KEY_HOMEPAGE; irq = asic3_irq_base( &hx4700_asic3.dev ) + ASIC3_GPIOD_IRQ_BASE + GPIOD_KEY_AP4_N; err = request_irq( irq, key_isr, SA_INTERRUPT, "HX4700 AP4 Key", (void *)&asic3_key[1] ); if (err) { printk(KERN_ERR "GPIOD_KEY_AP4_N: can't request IRQ\n"); } else { set_irq_type( irq, IRQT_FALLING ); asic3_key[1].irq = irq; } asic3_key[2].gpiod_val = GPIOD_AUD_RECORD_N; asic3_key[2].gpiod_bit = (1<<GPIOD_AUD_RECORD_N); asic3_key[2].rising = 0; asic3_key[2].key = _KEY_RECORD; irq = asic3_irq_base( &hx4700_asic3.dev ) + ASIC3_GPIOD_IRQ_BASE + GPIOD_AUD_RECORD_N; err = request_irq( irq, key_isr, SA_INTERRUPT, "HX4700 Record", (void *)&asic3_key[2] ); if (err) { printk(KERN_ERR "GPIOD_AUD_RECORD_N: can't request IRQ\n"); } else { set_irq_type( irq, IRQT_FALLING ); asic3_key[2].irq = irq; } return 0;}static intts_remove (struct device *dev){ int i; struct touchscreen_data *ts = dev_get_drvdata(dev); input_unregister_device (ts->input); del_timer_sync (&ts->timer); free_irq (ts->irq, ts); for (i=0; i<3; i++) { if (asic3_key[i].irq != 0) free_irq( asic3_key[i].irq, &asic3_key[i] ); } kfree(ts); pxa_set_cken(CKEN3_SSP2, 0); return 0;}static intts_suspend (struct device *dev, pm_message_t state){ disable_irq(HX4700_IRQ(TOUCHPANEL_IRQ_N)); return 0;}static intts_resume (struct device *dev){ struct touchscreen_data *ts = dev_get_drvdata(dev); ts->state = STATE_WAIT_FOR_TOUCH; ssp_init(); enable_irq(HX4700_IRQ(TOUCHPANEL_IRQ_N)); return 0;}static struct device_driver ts_driver = { .name = "hx4700-ts", .bus = &platform_bus_type, .probe = ts_probe, .remove = ts_remove, .suspend = ts_suspend, .resume = ts_resume};static int tssim_init(void);static intts_module_init (void){ printk(KERN_NOTICE "hx4700 Touch Screen Driver\n"); if(tssim_init()) { printk(KERN_NOTICE " TS Simulator Not Installed\n"); } else { printk(KERN_NOTICE " TS Simulator Installed\n"); } return driver_register(&ts_driver);}static void tssim_exit(void);static voidts_module_cleanup (void){ tssim_exit(); driver_unregister (&ts_driver);}/************* Code for Touch Screen Simulation for FBVNC Server **********/static dev_t dev;static struct cdev *cdev;static long a0 = -1122, a2 = 33588528, a4 = 1452, a5 = -2970720, a6 = 65536;/* The input into the input subsystem is prior to correction from calibration. * So we have to undo the effects of the calibration. It's actually a * complicated equation where the calibrated value of X depends on the * uncalibrated values of X and Y. Fortunately, at least on the hx4700, the * multiplier for the Y value is zero, so I assume that here. It is a shame * that the tslib does not allow multiple inputs. Then we could do another * driver for this (as it was originally) that give input that does not * require calibration. */static inttssim_ioctl(struct inode *inode, struct file *fp, unsigned int ioctlnum, unsigned long parm){ switch(ioctlnum) { case 0: a0 = parm; break; case 1: break; case 2: a2 = parm; break; case 3: break; case 4: a4 = parm; break; case 5: a5 = parm; break; case 6: a6 = parm; printk(KERN_DEBUG "a0 = %ld, a2 = %ld, a4 = %ld, a5 = %ld, a6 = %ld\n", a0, a2, a4, a5, a6); break; default: return -ENOTTY; } return 0;}static inttssim_open(struct inode *inode, struct file *fp){ /* Nothing to do here */ return 0;}static ssize_ttssim_write(struct file *fp, const char __user *data, size_t bytes, loff_t *offset){ unsigned long pressure; long y; long x; x = data[0] | (data[1] << 8) | (data[2] << 16) | (data[3] << 24); data += 4; y = data[0] | (data[1] << 8) | (data[2] << 16) | (data[3] << 24); data += 4; pressure = data[0] | (data[1] << 8) | (data[2] << 16) | (data[3] << 24); data += 4; input_report_abs(ts_data->input, ABS_PRESSURE, pressure?1:0); input_report_abs(ts_data->input, ABS_X, ((x * a6) - a2)/a0); input_report_abs(ts_data->input, ABS_Y, ((y * a6) - a5)/a4); input_sync(ts_data->input); return bytes;}int tssim_close(struct inode *inode, struct file *fp){ return 0;}struct file_operations fops = { THIS_MODULE, .write = tssim_write, .open = tssim_open, .release = tssim_close, .ioctl = tssim_ioctl,};static int battery_class;static int get_min_voltage(struct battery *b){ return 1000;}static int get_max_voltage(struct battery *b){ return 1400; /* mV */}static int get_max_charge(struct battery *b){ return 100;}static int get_voltage(struct battery *b){ static int battery_sample; if(!down_interruptible(&serial_mutex)) { int i; int ssrval; while(!(SSSR_P2 & (1 << 2))) ; SSDR_P2 = 0xe70000; while(!(SSSR_P2 & (1 << 2))) ; SSDR_P2 = 0xe70000; while(!(SSSR_P2 & (1 << 2))) ; SSDR_P2 = 0xd00000; /* Dummy command to allow pen interrupts again */ for(i = 0; i < 10; i++) { ssrval = SSSR_P2; if(ssrval & (1 << 3)) { /* Look at Rx Not Empty bit */ int number_of_entries_in_fifo; number_of_entries_in_fifo = ((ssrval >> 12) & 0xf) + 1; if(number_of_entries_in_fifo == 3) { break; } } msleep(1); } if(i < 1000) { (void) SSDR_P2; battery_sample = SSDR_P2 & 0xfff; (void) SSDR_P2; } else { /* Make sure the FIFO is empty */ while(SSSR_P2 & (1 << 3)) { (void) SSDR_P2; } battery_sample = -1; } up(&serial_mutex); } return battery_sample;}static int get_charge(struct battery *b){ return 100;}static int get_status(struct battery *b){ return 1;}static struct battery hx4700_power = { .name = "hx4700_backup", .id = "backup", .get_min_voltage = get_min_voltage, .get_min_current = 0, .get_min_charge = 0, .get_max_voltage = get_max_voltage, .get_max_current = 0, .get_max_charge = get_max_charge, .get_temp = 0, .get_voltage = get_voltage, .get_current = 0, .get_charge = get_charge, .get_status = get_status,};static intbattery_class_uevent(struct class_device *dev, char **envp, int num_envp, char *buffer, int buffer_size){ return 0;}static voidbattery_class_release(struct class_device *dev){}static voidbattery_class_class_release(struct class *class){}static inttssim_init(void){ int retval; retval = alloc_chrdev_region(&dev, 0, 1, "tssim"); if(retval) { printk(KERN_ERR "TSSIM Unable to allocate device numbers\n"); return retval; } cdev = cdev_alloc(); cdev->owner = THIS_MODULE; cdev->ops = &fops; retval = cdev_add(cdev, dev, 1); if(retval) { printk(KERN_ERR "Unable to add cdev\n"); unregister_chrdev_region(dev, 1); return retval; } battery_class = 0; if(battery_class_register(&hx4700_power)) { printk(KERN_ERR "hx4700_ts: Could not register battery class\n"); } else { battery_class = 1; hx4700_power.class_dev.class->uevent = battery_class_uevent; hx4700_power.class_dev.class->release = battery_class_release; hx4700_power.class_dev.class->class_release = battery_class_class_release; } return 0;}static voidtssim_exit(void){ cdev_del(cdev); unregister_chrdev_region(dev, 1); if(battery_class) { battery_class_unregister(&hx4700_power); } return;}module_init(ts_module_init);module_exit(ts_module_cleanup);MODULE_LICENSE("GPL");MODULE_AUTHOR("Aric Blumer, SDG Systems, LLC");MODULE_DESCRIPTION("hx4700 Touch Screen Driver");
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -