📄 touchscreen.patch
字号:
+ int updown;++ data0 = readl(base_addr+S3C2410_ADCDAT0);+ data1 = readl(base_addr+S3C2410_ADCDAT1);++ updown = (!(data0 & S3C2410_ADCDAT0_UPDOWN)) && (!(data1 & S3C2410_ADCDAT0_UPDOWN));++ /* TODO we should never get an interrupt with updown set while+ * the timer is running, but maybe we ought to verify that the+ * timer isn't running anyways. */++ if (updown)+ touch_timer_fire(0);++ return IRQ_HANDLED;+}+++static irqreturn_t stylus_action(int irq, void *dev_id)+{+ unsigned long data0;+ unsigned long data1;++ data0 = readl(base_addr+S3C2410_ADCDAT0);+ data1 = readl(base_addr+S3C2410_ADCDAT1);++ ts.xp += data0 & S3C2410_ADCDAT0_XPDATA_MASK;+ ts.yp += data1 & S3C2410_ADCDAT1_YPDATA_MASK;+ ts.count++;++ if (ts.count < (1<<ts.shift)) {+ writel(S3C2410_ADCTSC_PULL_UP_DISABLE | AUTOPST, base_addr+S3C2410_ADCTSC);+ writel(readl(base_addr+S3C2410_ADCCON) | S3C2410_ADCCON_ENABLE_START, base_addr+S3C2410_ADCCON);+ } else {+ mod_timer(&touch_timer, jiffies+1);+ writel(WAIT4INT(1), base_addr+S3C2410_ADCTSC);+ }++ return IRQ_HANDLED;+}++static struct clk *adc_clock;++/*+ * The functions for inserting/removing us as a module.+ */++static int __init s3c2410ts_probe(struct platform_device *pdev)+{+ struct s3c2410_ts_mach_info *info;+ struct input_dev *input_dev;++ info = ( struct s3c2410_ts_mach_info *)pdev->dev.platform_data;++ if (!info)+ {+ printk(KERN_ERR "Hm... too bad : no platform data for ts\n");+ return -EINVAL;+ }++#ifdef CONFIG_TOUCHSCREEN_S3C2410_DEBUG+ printk(DEBUG_LVL "Entering s3c2410ts_init\n");+#endif++ adc_clock = clk_get(NULL, "adc");+ if (!adc_clock) {+ printk(KERN_ERR "failed to get adc clock source\n");+ return -ENOENT;+ }+ clk_enable(adc_clock);++#ifdef CONFIG_TOUCHSCREEN_S3C2410_DEBUG+ printk(DEBUG_LVL "got and enabled clock\n");+#endif++ base_addr=ioremap(S3C2410_PA_ADC,0x20);+ if (base_addr == NULL) {+ printk(KERN_ERR "Failed to remap register block\n");+ return -ENOMEM;+ }+++ /* Configure GPIOs */+ s3c2410_ts_connect();++ if ((info->presc&0xff) > 0)+ writel(S3C2410_ADCCON_PRSCEN | S3C2410_ADCCON_PRSCVL(info->presc&0xFF),\+ base_addr+S3C2410_ADCCON);+ else+ writel(0,base_addr+S3C2410_ADCCON);+++ /* Initialise registers */+ if ((info->delay&0xffff) > 0)+ writel(info->delay & 0xffff, base_addr+S3C2410_ADCDLY);++ writel(WAIT4INT(0), base_addr+S3C2410_ADCTSC);++ /* Initialise input stuff */+ memset(&ts, 0, sizeof(struct s3c2410ts));+ input_dev = input_allocate_device();++ if (!input_dev) {+ printk(KERN_ERR "Unable to allocate the input device !!\n");+ return -ENOMEM;+ }++ ts.dev = input_dev;+ ts.dev->evbit[0] = BIT(EV_SYN) | BIT(EV_KEY) | BIT(EV_ABS);+ ts.dev->keybit[LONG(BTN_TOUCH)] = BIT(BTN_TOUCH);+ input_set_abs_params(ts.dev, ABS_X, 0, 0x3FF, 0, 0);+ input_set_abs_params(ts.dev, ABS_Y, 0, 0x3FF, 0, 0);+ input_set_abs_params(ts.dev, ABS_PRESSURE, 0, 1, 0, 0);++ ts.dev->private = &ts;+ ts.dev->name = s3c2410ts_name;+ ts.dev->id.bustype = BUS_RS232;+ ts.dev->id.vendor = 0xDEAD;+ ts.dev->id.product = 0xBEEF;+ ts.dev->id.version = S3C2410TSVERSION;++ ts.shift = info->oversampling_shift;++ /* Get irqs */+ if (request_irq(IRQ_ADC, stylus_action, IRQF_SAMPLE_RANDOM,+ "s3c2410_action", ts.dev)) {+ printk(KERN_ERR "s3c2410_ts.c: Could not allocate ts IRQ_ADC !\n");+ iounmap(base_addr);+ return -EIO;+ }+ if (request_irq(IRQ_TC, stylus_updown, IRQF_SAMPLE_RANDOM,+ "s3c2410_action", ts.dev)) {+ printk(KERN_ERR "s3c2410_ts.c: Could not allocate ts IRQ_TC !\n");+ iounmap(base_addr);+ return -EIO;+ }++ printk(KERN_INFO "%s successfully loaded\n", s3c2410ts_name);++ /* All went ok, so register to the input system */+ input_register_device(ts.dev);++ return 0;+}++static int s3c2410ts_remove(struct platform_device *pdev)+{+ disable_irq(IRQ_ADC);+ disable_irq(IRQ_TC);+ free_irq(IRQ_TC,ts.dev);+ free_irq(IRQ_ADC,ts.dev);++ if (adc_clock) {+ clk_disable(adc_clock);+ clk_put(adc_clock);+ adc_clock = NULL;+ }++ input_unregister_device(ts.dev);+ iounmap(base_addr);++ return 0;+}++#ifdef CONFIG_PM+static int s3c2410ts_suspend(struct platform_device *pdev, pm_message_t state)+{+ writel(TSC_SLEEP, base_addr+S3C2410_ADCTSC);+ writel(readl(base_addr+S3C2410_ADCCON) | S3C2410_ADCCON_STDBM,+ base_addr+S3C2410_ADCCON);++ disable_irq(IRQ_ADC);+ disable_irq(IRQ_TC);++ clk_disable(adc_clock);++ return 0;+}++static int s3c2410ts_resume(struct platform_device *pdev)+{+ struct s3c2410_ts_mach_info *info =+ ( struct s3c2410_ts_mach_info *)pdev->dev.platform_data;++ clk_enable(adc_clock);+ msleep(1);++ enable_irq(IRQ_ADC);+ enable_irq(IRQ_TC);++ if ((info->presc&0xff) > 0)+ writel(S3C2410_ADCCON_PRSCEN | S3C2410_ADCCON_PRSCVL(info->presc&0xFF),\+ base_addr+S3C2410_ADCCON);+ else+ writel(0,base_addr+S3C2410_ADCCON);++ /* Initialise registers */+ if ((info->delay&0xffff) > 0)+ writel(info->delay & 0xffff, base_addr+S3C2410_ADCDLY);++ writel(WAIT4INT(0), base_addr+S3C2410_ADCTSC);++ return 0;+}++#else+#define s3c2410ts_suspend NULL+#define s3c2410ts_resume NULL+#endif++static struct platform_driver s3c2410ts_driver = {+ .driver = {+ .name = "s3c2410-ts",+ .owner = THIS_MODULE,+ },+ .probe = s3c2410ts_probe,+ .remove = s3c2410ts_remove,+ .suspend = s3c2410ts_suspend,+ .resume = s3c2410ts_resume,++};+++static int __init s3c2410ts_init(void)+{+ return platform_driver_register(&s3c2410ts_driver);+}++static void __exit s3c2410ts_exit(void)+{+ platform_driver_unregister(&s3c2410ts_driver);+}++module_init(s3c2410ts_init);+module_exit(s3c2410ts_exit);++/*+ Local variables:+ compile-command: "make ARCH=arm CROSS_COMPILE=/usr/local/arm/3.3.2/bin/arm-linux- -k -C ../../.."+ c-basic-offset: 8+ End:+*/diff --git a/include/asm-arm/arch-s3c2410/regs-adc.h b/include/asm-arm/arch-s3c2410/regs-adc.hindex 3196a28..c7f2319 100644--- a/include/asm-arm/arch-s3c2410/regs-adc.h+++ b/include/asm-arm/arch-s3c2410/regs-adc.h@@ -41,7 +41,7 @@ #define S3C2410_ADCTSC_XM_SEN (1<<5) #define S3C2410_ADCTSC_XP_SEN (1<<4) #define S3C2410_ADCTSC_PULL_UP_DISABLE (1<<3) #define S3C2410_ADCTSC_AUTO_PST (1<<2)-#define S3C2410_ADCTSC_XY_PST (0x3<<0)+#define S3C2410_ADCTSC_XY_PST(x) (((x)&0x3)<<0) /* ADCDAT0 Bits */ #define S3C2410_ADCDAT0_UPDOWN (1<<15)diff --git a/include/asm-arm/arch-s3c2410/ts.h b/include/asm-arm/arch-s3c2410/ts.hnew file mode 100644index 0000000..8566f25--- /dev/null+++ b/include/asm-arm/arch-s3c2410/ts.h@@ -0,0 +1,28 @@+/* linux/include/asm/arch-s3c2410/ts.h+ *+ * Copyright (c) 2005 Arnaud Patard <arnaud.patard@rtp-net.org>+ *+ *+ * This program is free software; you can redistribute it and/or modify+ * it under the terms of the GNU General Public License version 2 as+ * published by the Free Software Foundation.+ *+ *+ * Changelog:+ * 24-Mar-2005 RTP Created file+ * 03-Aug-2005 RTP Renamed to ts.h+ */++#ifndef __ASM_ARM_TS_H+#define __ASM_ARM_TS_H++struct s3c2410_ts_mach_info {+ int delay;+ int presc;+ int oversampling_shift;+};++void __init set_s3c2410ts_info(struct s3c2410_ts_mach_info *hard_s3c2410ts_info);++#endif /* __ASM_ARM_TS_H */+
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -