From 54f6fd272bec8e57f1040fc0fa1d954051fc275c Mon Sep 17 00:00:00 2001 From: Michael Trimarchi Date: Tue, 22 Sep 2009 19:36:37 +0200 Subject: Remove dependence on old netdev operations Remove the dependence to the OLD NET DEV operation Signed-off-by: Michael Trimarchi --- drivers/ar6000/ar6000/ar6000_drv.c | 20 ++++++++++++-------- 1 file changed, 12 insertions(+), 8 deletions(-) (limited to 'drivers') diff --git a/drivers/ar6000/ar6000/ar6000_drv.c b/drivers/ar6000/ar6000/ar6000_drv.c index 21504f221dd..2941d5ed8c2 100644 --- a/drivers/ar6000/ar6000/ar6000_drv.c +++ b/drivers/ar6000/ar6000/ar6000_drv.c @@ -221,6 +221,15 @@ static void ar6000_detect_error(unsigned long ptr); static struct net_device_stats *ar6000_get_stats(struct net_device *dev); static struct iw_statistics *ar6000_get_iwstats(struct net_device * dev); +static struct net_device_ops ar6000_netdev_ops = { + .ndo_open = ar6000_open, + .ndo_stop = ar6000_close, + .ndo_start_xmit = ar6000_data_tx, + .ndo_validate_addr = eth_validate_addr, + .ndo_do_ioctl = ar6000_ioctl, + .ndo_get_stats = &ar6000_get_stats, +}; + /* * HTC service connection handlers */ @@ -858,20 +867,15 @@ ar6000_avail_ev(HTC_HANDLE HTCHandle) spin_lock_init(&ar->arLock); /* Don't install the init function if BMI is requested */ - if(!bmienable) - { - dev->init = ar6000_init; + if (!bmienable) { + ar6000_netdev_ops.ndo_init = ar6000_init; } else { AR_DEBUG_PRINTF(" BMI enabled \n"); } - dev->open = &ar6000_open; - dev->stop = &ar6000_close; - dev->hard_start_xmit = &ar6000_data_tx; - dev->get_stats = &ar6000_get_stats; + dev->netdev_ops = &ar6000_netdev_ops; /* dev->tx_timeout = ar6000_tx_timeout; */ - dev->do_ioctl = &ar6000_ioctl; dev->watchdog_timeo = AR6000_TX_TIMEOUT; ar6000_ioctl_iwsetup(&ath_iw_handler_def); dev->wireless_handlers = &ath_iw_handler_def; -- cgit v1.2.3 From 7ddf2bb46771e10d4cc7da94b3c1210426806def Mon Sep 17 00:00:00 2001 From: Nelson Castillo Date: Fri, 18 Sep 2009 01:45:39 -0500 Subject: Make s3c TS driver use s3c-adc API I had a patch by Vasily Khoruzhick in the linux-arm-kernel as a guide for some of the changes. Signed-off-by: Nelson Castillo --- drivers/input/touchscreen/s3c2410_ts.c | 136 ++++++++++++--------------------- 1 file changed, 49 insertions(+), 87 deletions(-) (limited to 'drivers') diff --git a/drivers/input/touchscreen/s3c2410_ts.c b/drivers/input/touchscreen/s3c2410_ts.c index 23d7e28e460..760b13c7eb8 100644 --- a/drivers/input/touchscreen/s3c2410_ts.c +++ b/drivers/input/touchscreen/s3c2410_ts.c @@ -64,6 +64,7 @@ #include #include #include +#include #include "ts_filter_chain.h" @@ -78,12 +79,6 @@ S3C2410_ADCTSC_XP_SEN | \ S3C2410_ADCTSC_XY_PST(3)) -#define AUTOPST (S3C2410_ADCTSC_YM_SEN | \ - S3C2410_ADCTSC_YP_SEN | \ - S3C2410_ADCTSC_XP_SEN | \ - S3C2410_ADCTSC_AUTO_PST | \ - S3C2410_ADCTSC_XY_PST(0)) - #define DEBUG_LVL KERN_DEBUG MODULE_AUTHOR("Arnaud Patard "); @@ -110,10 +105,12 @@ static char *s3c2410ts_name = "s3c2410 TouchScreen"; struct s3c2410ts { struct input_dev *dev; + struct s3c_adc_client *adc_client; struct ts_filter_chain *chain; int is_down; int state; struct kfifo *event_fifo; + unsigned adc_selected; }; static struct s3c2410ts ts; @@ -132,12 +129,26 @@ static inline void s3c2410_ts_connect(void) s3c2410_gpio_cfgpin(S3C2410_GPG15, S3C2410_GPG15_nYPON); } +static void ts_adc_timer_f(unsigned long data); +static struct timer_list ts_adc_timer = TIMER_INITIALIZER(ts_adc_timer_f, 0, 0); + +static void ts_adc_timer_f(unsigned long data) +{ + if (s3c_adc_start(ts.adc_client, 0, 1)) + mod_timer(&ts_adc_timer, jiffies + 1); +} + +void adc_selected_f(unsigned selected) +{ + ts.adc_selected = selected; +} + static void s3c2410_ts_start_adc_conversion(void) { - 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); + if (ts.adc_selected) + mod_timer(&ts_adc_timer, jiffies + 1); + else + ts_adc_timer_f(0); } /* @@ -282,21 +293,25 @@ static irqreturn_t stylus_updown(int irq, void *dev_id) return IRQ_HANDLED; } -static irqreturn_t stylus_action(int irq, void *dev_id) +static void stylus_adc_action(unsigned p0, unsigned p1, unsigned *conv_left) { int buf[3]; - /* Grab the ADC results. */ - buf[1] = readl(base_addr + S3C2410_ADCDAT0) & - S3C2410_ADCDAT0_XPDATA_MASK; - buf[2] = readl(base_addr + S3C2410_ADCDAT1) & - S3C2410_ADCDAT1_YPDATA_MASK; + /* TODO: Do we really need this? */ + if (p0 & S3C2410_ADCDAT0_AUTO_PST || + p1 & S3C2410_ADCDAT1_AUTO_PST) { + *conv_left = 1; + return; + } + + buf[1] = p0; + buf[2] = p1; switch (ts_filter_chain_feed(ts.chain, &buf[1])) { case 0: /* The filter wants more points. */ - s3c2410_ts_start_adc_conversion(); - return IRQ_HANDLED; + *conv_left = 1; + return; case 1: /* We have a point from the filters or no filtering enabled. */ buf[0] = 'P'; @@ -309,7 +324,7 @@ static irqreturn_t stylus_action(int irq, void *dev_id) /* Error. Ignore the event. */ ts_filter_chain_clear(ts.chain); writel(WAIT4INT(1), base_addr + S3C2410_ADCTSC); - return IRQ_HANDLED; + return; }; if (unlikely(__kfifo_put(ts.event_fifo, (unsigned char *)buf, @@ -319,11 +334,9 @@ static irqreturn_t stylus_action(int irq, void *dev_id) writel(WAIT4INT(1), base_addr + S3C2410_ADCTSC); mod_timer(&event_send_timer, jiffies + 1); - return IRQ_HANDLED; + return; } -static struct clk *adc_clock; - /* * The functions for inserting/removing us as a module. */ @@ -349,17 +362,6 @@ static int __init s3c2410ts_probe(struct platform_device *pdev) printk(DEBUG_LVL "Entering s3c2410ts_init\n"); #endif - adc_clock = clk_get(NULL, "adc"); - if (!adc_clock) { - dev_err(&pdev->dev, "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) { dev_err(&pdev->dev, "Failed to remap register block\n"); @@ -372,23 +374,22 @@ static int __init s3c2410ts_probe(struct platform_device *pdev) if (!strcmp(pdev->name, "s3c2410-ts")) 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(); + ts.adc_client = + s3c_adc_register(pdev, adc_selected_f, stylus_adc_action, 1); + if (!ts.adc_client) { + dev_err(&pdev->dev, + "Unable to register s3c2410_ts as s3_adc client\n"); + iounmap(base_addr); + ret = -EIO; + goto bail0; + } + + input_dev = input_allocate_device(); if (!input_dev) { dev_err(&pdev->dev, "Unable to allocate the input device\n"); ret = -ENOMEM; @@ -423,18 +424,10 @@ static int __init s3c2410ts_probe(struct platform_device *pdev) ts_filter_chain_clear(ts.chain); - /* Get irqs */ - if (request_irq(IRQ_ADC, stylus_action, IRQF_SAMPLE_RANDOM, - "s3c2410_action", ts.dev)) { - dev_err(&pdev->dev, "Could not allocate ts IRQ_ADC !\n"); - iounmap(base_addr); - ret = -EIO; - goto bail3; - } + /* Get IRQ. */ if (request_irq(IRQ_TC, stylus_updown, IRQF_SAMPLE_RANDOM, "s3c2410_action", ts.dev)) { dev_err(&pdev->dev, "Could not allocate ts IRQ_TC !\n"); - free_irq(IRQ_ADC, ts.dev); iounmap(base_addr); ret = -EIO; goto bail4; @@ -445,6 +438,7 @@ static int __init s3c2410ts_probe(struct platform_device *pdev) /* All went ok, so register to the input system */ rc = input_register_device(ts.dev); if (rc) { + dev_info(&pdev->dev, "Could not register input device\n"); ret = -EIO; goto bail5; } @@ -453,13 +447,9 @@ static int __init s3c2410ts_probe(struct platform_device *pdev) bail5: free_irq(IRQ_TC, ts.dev); - free_irq(IRQ_ADC, ts.dev); - clk_disable(adc_clock); iounmap(base_addr); disable_irq(IRQ_TC); bail4: - disable_irq(IRQ_ADC); -bail3: ts_filter_chain_destroy(ts.chain); kfifo_free(ts.event_fifo); bail2: @@ -473,17 +463,10 @@ bail0: 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; - } + s3c_adc_release(ts.adc_client); input_unregister_device(ts.dev); iounmap(base_addr); @@ -501,38 +484,17 @@ static int s3c2410ts_suspend(struct platform_device *pdev, pm_message_t state) 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); - mdelay(1); - ts_filter_chain_clear(ts.chain); - 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; -- cgit v1.2.3 From d44cb10f4209f6a2181b778c493d36bc5eac0f0c Mon Sep 17 00:00:00 2001 From: Nelson Castillo Date: Tue, 22 Sep 2009 05:23:28 -0500 Subject: s3_ts: cleanups General cleanups. Now we pass checkpatch.pl. Signed-off-by: Nelson Castillo --- drivers/input/touchscreen/s3c2410_ts.c | 192 ++++++++++++++++----------------- 1 file changed, 94 insertions(+), 98 deletions(-) (limited to 'drivers') diff --git a/drivers/input/touchscreen/s3c2410_ts.c b/drivers/input/touchscreen/s3c2410_ts.c index 760b13c7eb8..d78f4662929 100644 --- a/drivers/input/touchscreen/s3c2410_ts.c +++ b/drivers/input/touchscreen/s3c2410_ts.c @@ -19,7 +19,7 @@ * ChangeLog * * 2004-09-05: Herbert Pƶtzl - * - added clock (de-)allocation code + * - Added clock (de-)allocation code * * 2005-03-06: Arnaud Patard * - h1940_ -> s3c2410 (this driver is now also used on the n30 @@ -38,11 +38,15 @@ * - Add proper support for S32440 * * 2008-06-23: Andy Green - * - removed averaging system - * - added generic Touchscreen filter stuff + * - Removed averaging system + * - Added generic Touchscreen filter stuff * * 2008-11-27: Nelson Castillo - * - improve interrupt handling + * - Improve interrupt handling + * + * 2009-04-09: Nelson Castillo + * - Use s3c-adc API (Vasily Khoruzhick provided + * a working example for a simpler version of this driver). */ #include @@ -57,7 +61,7 @@ #include #include #include -#include +#include #include #include @@ -71,15 +75,20 @@ /* For ts.dev.id.version */ #define S3C2410TSVERSION 0x0101 -#define TSC_SLEEP (S3C2410_ADCTSC_PULL_UP_DISABLE | S3C2410_ADCTSC_XY_PST(0)) +#define WAIT4INT(x) (((x)<<8) | \ + S3C2410_ADCTSC_YM_SEN | \ + S3C2410_ADCTSC_YP_SEN | \ + S3C2410_ADCTSC_XP_SEN | \ + S3C2410_ADCTSC_XY_PST(3)) -#define WAIT4INT(x) (((x)<<8) | \ - S3C2410_ADCTSC_YM_SEN | \ - S3C2410_ADCTSC_YP_SEN | \ - S3C2410_ADCTSC_XP_SEN | \ - S3C2410_ADCTSC_XY_PST(3)) +#define TSPRINTK(fmt, args...) \ + printk(KERN_DEBUG "%s: " fmt, __func__ , ## args) +#ifdef CONFIG_TOUCHSCREEN_S3C2410_DEBUG +# define DPRINTK TSPRINTK +#else +# define DPRINTK(fmt, args...) +#endif -#define DEBUG_LVL KERN_DEBUG MODULE_AUTHOR("Arnaud Patard "); MODULE_DESCRIPTION("s3c2410 touchscreen driver"); @@ -92,24 +101,22 @@ MODULE_LICENSE("GPL"); static char *s3c2410ts_name = "s3c2410 TouchScreen"; #define TS_RELEASE_TIMEOUT (HZ >> 7 ? HZ >> 7 : 1) /* 8ms (5ms if HZ is 200) */ -#define TS_EVENT_FIFO_SIZE (2 << 6) /* must be a power of 2 */ - -#define TS_STATE_STANDBY 0 /* initial state */ -#define TS_STATE_PRESSED 1 -#define TS_STATE_RELEASE_PENDING 2 -#define TS_STATE_RELEASE 3 +#define TS_EVENT_FIFO_SIZE (2 << 6) /* Must be a power of 2. */ /* * Per-touchscreen data. */ +enum ts_state {TS_STATE_STANDBY, TS_STATE_PRESSED, TS_STATE_RELEASE_PENDING, + TS_STATE_RELEASE}; + struct s3c2410ts { struct input_dev *dev; - struct s3c_adc_client *adc_client; struct ts_filter_chain *chain; + enum ts_state state; int is_down; - int state; struct kfifo *event_fifo; + struct s3c_adc_client *adc_client; unsigned adc_selected; }; @@ -129,6 +136,10 @@ static inline void s3c2410_ts_connect(void) s3c2410_gpio_cfgpin(S3C2410_GPG15, S3C2410_GPG15_nYPON); } +/* + * Code that starts ADC conversions. + */ + static void ts_adc_timer_f(unsigned long data); static struct timer_list ts_adc_timer = TIMER_INITIALIZER(ts_adc_timer_f, 0, 0); @@ -138,11 +149,6 @@ static void ts_adc_timer_f(unsigned long data) mod_timer(&ts_adc_timer, jiffies + 1); } -void adc_selected_f(unsigned selected) -{ - ts.adc_selected = selected; -} - static void s3c2410_ts_start_adc_conversion(void) { if (ts.adc_selected) @@ -151,6 +157,12 @@ static void s3c2410_ts_start_adc_conversion(void) ts_adc_timer_f(0); } +/* Callback for the s3c-adc API. */ +void adc_selected_f(unsigned selected) +{ + ts.adc_selected = selected; +} + /* * Just send the input events. */ @@ -172,18 +184,14 @@ static void ts_input_report(int event, int coords[]) input_report_key(ts.dev, BTN_TOUCH, 1); input_report_abs(ts.dev, ABS_PRESSURE, 1); -#ifdef CONFIG_TOUCHSCREEN_S3C2410_DEBUG - printk(DEBUG_LVL "T:%06d %6s (X:%03d, Y:%03d)\n", - (int)tv.tv_usec, s[event], coords[0], coords[1]); -#endif + DPRINTK("T:%06d %6s (X:%03d, Y:%03d)\n", + (int)tv.tv_usec, s[event], coords[0], coords[1]); } else { input_report_key(ts.dev, BTN_TOUCH, 0); input_report_abs(ts.dev, ABS_PRESSURE, 0); -#ifdef CONFIG_TOUCHSCREEN_S3C2410_DEBUG - printk(DEBUG_LVL "T:%06d %6s\n", - (int)tv.tv_usec, s[event]); -#endif + DPRINTK("T:%06d %6s\n", + (int)tv.tv_usec, s[event]); } input_sync(ts.dev); @@ -210,7 +218,7 @@ static void event_send_timer_f(unsigned long data) switch (event_type) { case 'D': if (ts.state == TS_STATE_RELEASE_PENDING) - /* Ignore short UP event */ + /* Ignore short UP event. */ ts.state = TS_STATE_PRESSED; break; @@ -219,21 +227,21 @@ static void event_send_timer_f(unsigned long data) break; case 'P': - if (ts.is_down) /* stylus_action needs a conversion */ + if (ts.is_down) /* Stylus_action needs a conversion. */ s3c2410_ts_start_adc_conversion(); if (unlikely(__kfifo_get(ts.event_fifo, (unsigned char *)buf, sizeof(int) * 2) - != sizeof(int) * 2)) - goto ts_exit_error; + != sizeof(int) * 2)) { + /* This will only happen if we have a bug. */ + TSPRINTK("Invalid packet\n"); + return; + } ts_input_report(IE_DOWN, buf); ts.state = TS_STATE_PRESSED; break; - - default: - goto ts_exit_error; } noop_counter = 0; @@ -254,11 +262,6 @@ static void event_send_timer_f(unsigned long data) } else { mod_timer(&event_send_timer, jiffies + TS_RELEASE_TIMEOUT); } - - return; - -ts_exit_error: /* should not happen unless we have a bug */ - printk(KERN_ERR __FILE__ ": event_send_timer_f failed\n"); } /* @@ -271,22 +274,23 @@ static irqreturn_t stylus_updown(int irq, void *dev_id) unsigned long data1; int event_type; - data0 = readl(base_addr+S3C2410_ADCDAT0); - data1 = readl(base_addr+S3C2410_ADCDAT1); + data0 = readl(base_addr + S3C2410_ADCDAT0); + data1 = readl(base_addr + S3C2410_ADCDAT1); - ts.is_down = (!(data0 & S3C2410_ADCDAT0_UPDOWN)) && - (!(data1 & S3C2410_ADCDAT0_UPDOWN)); + ts.is_down = !(data0 & S3C2410_ADCDAT0_UPDOWN) && + !(data1 & S3C2410_ADCDAT0_UPDOWN); event_type = ts.is_down ? 'D' : 'U'; if (unlikely(__kfifo_put(ts.event_fifo, (unsigned char *)&event_type, - sizeof(int)) != sizeof(int))) /* should not happen */ - printk(KERN_ERR __FILE__": stylus_updown lost event!\n"); + sizeof(int)) != sizeof(int))) + /* Only happens if we have a bug. */ + TSPRINTK("FIFO full\n"); if (ts.is_down) s3c2410_ts_start_adc_conversion(); else - writel(WAIT4INT(0), base_addr+S3C2410_ADCTSC); + writel(WAIT4INT(0), base_addr + S3C2410_ADCTSC); mod_timer(&event_send_timer, jiffies + 1); @@ -317,11 +321,9 @@ static void stylus_adc_action(unsigned p0, unsigned p1, unsigned *conv_left) buf[0] = 'P'; break; default: - printk(KERN_ERR __FILE__ - ":%d Invalid ts_filter_chain_feed return value.\n", - __LINE__); + TSPRINTK("invalid return value\n"); case -1: - /* Error. Ignore the event. */ + /* Too much noise. Ignore the event. */ ts_filter_chain_clear(ts.chain); writel(WAIT4INT(1), base_addr + S3C2410_ADCTSC); return; @@ -329,7 +331,8 @@ static void stylus_adc_action(unsigned p0, unsigned p1, unsigned *conv_left) if (unlikely(__kfifo_put(ts.event_fifo, (unsigned char *)buf, sizeof(int) * 3) != sizeof(int) * 3)) - printk(KERN_ERR __FILE__":stylus_action bug.\n"); + /* This will only happen if we have a bug. */ + TSPRINTK("FIFO full\n"); writel(WAIT4INT(1), base_addr + S3C2410_ADCTSC); mod_timer(&event_send_timer, jiffies + 1); @@ -352,24 +355,18 @@ static int __init s3c2410ts_probe(struct platform_device *pdev) info = (struct s3c2410_ts_mach_info *)pdev->dev.platform_data; - if (!info) - { - dev_err(&pdev->dev, "Hm... too bad: no platform data for ts\n"); + if (!info) { + dev_err(&pdev->dev, "No platform data\n"); return -EINVAL; } -#ifdef CONFIG_TOUCHSCREEN_S3C2410_DEBUG - printk(DEBUG_LVL "Entering s3c2410ts_init\n"); -#endif - - base_addr = ioremap(S3C2410_PA_ADC,0x20); + base_addr = ioremap(S3C2410_PA_ADC, 0x20); if (base_addr == NULL) { dev_err(&pdev->dev, "Failed to remap register block\n"); ret = -ENOMEM; goto bail0; } - /* If we acutally are a S3C2410: Configure GPIOs */ if (!strcmp(pdev->name, "s3c2410-ts")) s3c2410_ts_connect(); @@ -416,7 +413,7 @@ static int __init s3c2410ts_probe(struct platform_device *pdev) goto bail2; } - /* create the filter chain set up for the 2 coordinates we produce */ + /* Create the filter chain set up for the 2 coordinates we produce. */ ts.chain = ts_filter_chain_create(pdev, info->filter_config, 2); if (IS_ERR(ts.chain)) @@ -430,26 +427,26 @@ static int __init s3c2410ts_probe(struct platform_device *pdev) dev_err(&pdev->dev, "Could not allocate ts IRQ_TC !\n"); iounmap(base_addr); ret = -EIO; - goto bail4; + goto bail3; } dev_info(&pdev->dev, "Successfully loaded\n"); - /* All went ok, so register to the input system */ + /* All went ok. Register to the input system. */ rc = input_register_device(ts.dev); if (rc) { dev_info(&pdev->dev, "Could not register input device\n"); ret = -EIO; - goto bail5; + goto bail4; } return 0; -bail5: +bail4: free_irq(IRQ_TC, ts.dev); iounmap(base_addr); disable_irq(IRQ_TC); -bail4: +bail3: ts_filter_chain_destroy(ts.chain); kfifo_free(ts.event_fifo); bail2: @@ -464,7 +461,7 @@ bail0: static int s3c2410ts_remove(struct platform_device *pdev) { disable_irq(IRQ_TC); - free_irq(IRQ_TC,ts.dev); + free_irq(IRQ_TC, ts.dev); s3c_adc_release(ts.adc_client); input_unregister_device(ts.dev); @@ -478,12 +475,15 @@ static int s3c2410ts_remove(struct platform_device *pdev) } #ifdef CONFIG_PM + +#define TSC_SLEEP (S3C2410_ADCTSC_PULL_UP_DISABLE | \ + S3C2410_ADCTSC_XY_PST(0)) + 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); - + writel(TSC_SLEEP, base_addr + S3C2410_ADCTSC); + writel(readl(base_addr + S3C2410_ADCCON) | S3C2410_ADCCON_STDBM, + base_addr + S3C2410_ADCCON); disable_irq(IRQ_TC); return 0; @@ -492,10 +492,8 @@ static int s3c2410ts_suspend(struct platform_device *pdev, pm_message_t state) static int s3c2410ts_resume(struct platform_device *pdev) { ts_filter_chain_clear(ts.chain); - enable_irq(IRQ_TC); - - writel(WAIT4INT(0), base_addr+S3C2410_ADCTSC); + writel(WAIT4INT(0), base_addr + S3C2410_ADCTSC); return 0; } @@ -506,27 +504,25 @@ static int s3c2410ts_resume(struct platform_device *pdev) #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, - + .driver = { + .name = "s3c2410-ts", + .owner = THIS_MODULE, + }, + .probe = s3c2410ts_probe, + .remove = s3c2410ts_remove, + .suspend = s3c2410ts_suspend, + .resume = s3c2410ts_resume, }; static struct platform_driver s3c2440ts_driver = { - .driver = { - .name = "s3c2440-ts", - .owner = THIS_MODULE, - }, - .probe = s3c2410ts_probe, - .remove = s3c2410ts_remove, - .suspend = s3c2410ts_suspend, - .resume = s3c2410ts_resume, - + .driver = { + .name = "s3c2440-ts", + .owner = THIS_MODULE, + }, + .probe = s3c2410ts_probe, + .remove = s3c2410ts_remove, + .suspend = s3c2410ts_suspend, + .resume = s3c2410ts_resume, }; static int __init s3c2410ts_init(void) -- cgit v1.2.3 From b3ada7e6ee570963eb4e5189db8db9804c21491e Mon Sep 17 00:00:00 2001 From: Nelson Castillo Date: Tue, 22 Sep 2009 05:23:36 -0500 Subject: Fix Andy's email in filters. He is not reachable at the OM address. We need the right email if we send upstream. Signed-off-by: Nelson Castillo --- drivers/input/touchscreen/s3c2410_ts.c | 2 +- drivers/input/touchscreen/ts_filter.h | 2 +- drivers/input/touchscreen/ts_filter_chain.c | 2 +- drivers/input/touchscreen/ts_filter_chain.h | 2 +- drivers/input/touchscreen/ts_filter_mean.c | 2 +- drivers/input/touchscreen/ts_filter_mean.h | 2 +- drivers/input/touchscreen/ts_filter_median.c | 2 +- drivers/input/touchscreen/ts_filter_median.h | 2 +- 8 files changed, 8 insertions(+), 8 deletions(-) (limited to 'drivers') diff --git a/drivers/input/touchscreen/s3c2410_ts.c b/drivers/input/touchscreen/s3c2410_ts.c index d78f4662929..bcfdd00fa27 100644 --- a/drivers/input/touchscreen/s3c2410_ts.c +++ b/drivers/input/touchscreen/s3c2410_ts.c @@ -37,7 +37,7 @@ * 2007-05-23: Harald Welte * - Add proper support for S32440 * - * 2008-06-23: Andy Green + * 2008-06-23: Andy Green * - Removed averaging system * - Added generic Touchscreen filter stuff * diff --git a/drivers/input/touchscreen/ts_filter.h b/drivers/input/touchscreen/ts_filter.h index aac1e028d0b..632e5fb3f4e 100644 --- a/drivers/input/touchscreen/ts_filter.h +++ b/drivers/input/touchscreen/ts_filter.h @@ -4,7 +4,7 @@ /* * Touchscreen filter. * - * (c) 2008,2009 Andy Green + * (c) 2008,2009 Andy Green */ #include diff --git a/drivers/input/touchscreen/ts_filter_chain.c b/drivers/input/touchscreen/ts_filter_chain.c index a6346bdba3e..17793ace144 100644 --- a/drivers/input/touchscreen/ts_filter_chain.c +++ b/drivers/input/touchscreen/ts_filter_chain.c @@ -13,7 +13,7 @@ * along with this program; if not, write to the Free Software * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA * - * Copyright (c) 2008,2009 Andy Green + * Copyright (c) 2008,2009 Andy Green */ #include diff --git a/drivers/input/touchscreen/ts_filter_chain.h b/drivers/input/touchscreen/ts_filter_chain.h index 806bffe6c99..065a6a026d2 100644 --- a/drivers/input/touchscreen/ts_filter_chain.h +++ b/drivers/input/touchscreen/ts_filter_chain.h @@ -4,7 +4,7 @@ /* * Touchscreen filter chains. * - * (c) 2008,2009 Andy Green + * (c) 2008,2009 Andy Green */ #include "ts_filter.h" diff --git a/drivers/input/touchscreen/ts_filter_mean.c b/drivers/input/touchscreen/ts_filter_mean.c index 7621ded3ec8..0c604321713 100644 --- a/drivers/input/touchscreen/ts_filter_mean.c +++ b/drivers/input/touchscreen/ts_filter_mean.c @@ -14,7 +14,7 @@ * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA * * Copyright (c) 2008,2009 - * Andy Green + * Andy Green * Nelson Castillo * * Simple mean filter. diff --git a/drivers/input/touchscreen/ts_filter_mean.h b/drivers/input/touchscreen/ts_filter_mean.h index f5b5e4bbe10..80f9b215dff 100644 --- a/drivers/input/touchscreen/ts_filter_mean.h +++ b/drivers/input/touchscreen/ts_filter_mean.h @@ -9,7 +9,7 @@ * mean * * (c) 2008,2009 - * Andy Green + * Andy Green * Nelson Castillo */ diff --git a/drivers/input/touchscreen/ts_filter_median.c b/drivers/input/touchscreen/ts_filter_median.c index b8a6206d1b7..6f8aae5941d 100644 --- a/drivers/input/touchscreen/ts_filter_median.c +++ b/drivers/input/touchscreen/ts_filter_median.c @@ -13,7 +13,7 @@ * along with this program; if not, write to the Free Software * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA * - * Copyright (c) 2008 Andy Green + * Copyright (c) 2008 Andy Green * * * Median averaging stuff. We sort incoming raw samples into an array of diff --git a/drivers/input/touchscreen/ts_filter_median.h b/drivers/input/touchscreen/ts_filter_median.h index 1c19472e375..b13f361bb6a 100644 --- a/drivers/input/touchscreen/ts_filter_median.h +++ b/drivers/input/touchscreen/ts_filter_median.h @@ -8,7 +8,7 @@ * * median * - * (c) 2008 Andy Green + * (c) 2008 Andy Green */ struct ts_filter_median_configuration { -- cgit v1.2.3 From fc472e20c5999fbd1bfa2ebce8fef0454589fffc Mon Sep 17 00:00:00 2001 From: Nelson Castillo Date: Tue, 22 Sep 2009 05:23:43 -0500 Subject: Remove sort call from group filter This patch applies upstream feedback to the group filter. The algorithms are equivalent, thus we will get the same results after applying this patch. Signed-off-by: Nelson Castillo --- drivers/input/touchscreen/ts_filter_group.c | 178 +++++++++++++++++----------- 1 file changed, 106 insertions(+), 72 deletions(-) (limited to 'drivers') diff --git a/drivers/input/touchscreen/ts_filter_group.c b/drivers/input/touchscreen/ts_filter_group.c index b7c3f3ddcb9..93f8fc690e4 100644 --- a/drivers/input/touchscreen/ts_filter_group.c +++ b/drivers/input/touchscreen/ts_filter_group.c @@ -20,29 +20,39 @@ * * This filter is useful to reject samples that are not reliable. We consider * that a sample is not reliable if it deviates form the Majority. + * This filter mixes information from all the available dimensions. It means + * that for two dimensions we draw a rectangle where the though-to-be good + * points can be found. * - * 1) We collect S samples. + * The implementation would be more efficient with a double-linked list but + * let's keep it simple for now. * - * 2) For each dimension: - * - * - We sort the points. + * 1) We collect S samples and keep it in sorted sets. * - Points that are "close enough" are considered to be in the same set. - * - We choose the set with more elements. If more than "threshold" - * points are in this set we use the first and the last point of the set - * to define the valid range for this dimension [min, max], otherwise we - * discard all the points and go to step 1. + * We don't actually keep the sets but ranges of points. + * + * 2) For each dimension: + * - We choose the range with more elements. If more than "threshold" + * points are in this range we use the minimum and the maximum point + * of the range to define the valid range for this dimension [min, max], + * otherwise we discard all the points and the ranges and go to step 1. * * 3) We consider the unsorted S samples and try to feed them to the next * filter in the chain. If one of the points of each sample - * is not in the allowed range for its dimension, we discard the sample. + * is not in the allowed range for its dimension we discard the sample. * */ #include #include -#include #include "ts_filter_group.h" +struct coord_range { + int min; /* Minimum value of the range. */ + int max; /* Maximum value of the range */ + int N; /* Number of points in the range. */ +}; + struct ts_filter_group { /* Private filter configuration. */ struct ts_filter_group_configuration *config; @@ -52,13 +62,15 @@ struct ts_filter_group { int N; /* How many samples we have. */ int *samples[MAX_TS_FILTER_COORDS]; /* The samples: our input. */ - int *group_size; /* Used for temporal computations. */ - int *sorted_samples; /* Used for temporal computations. */ + /* Temporal values that help us compute range_min and range_max. */ + struct coord_range *ranges[MAX_TS_FILTER_COORDS]; /* Ranges. */ + int n_ranges[MAX_TS_FILTER_COORDS]; /* Number of ranges */ + /* Computed ranges that help us filter the points. */ int range_max[MAX_TS_FILTER_COORDS]; /* Max. computed ranges. */ int range_min[MAX_TS_FILTER_COORDS]; /* Min. computed ranges. */ - int tries_left; /* We finish if we don't get enough samples. */ + int tries_left; /* We finish if we can't get enough samples. */ int ready; /* If we are ready to deliver samples. */ int result; /* Index of the point being returned. */ }; @@ -70,10 +82,13 @@ struct ts_filter_group { static void ts_filter_group_clear_internal(struct ts_filter_group *tsfg, int attempts) { + int n; tsfg->N = 0; tsfg->tries_left = attempts; tsfg->ready = 0; tsfg->result = 0; + for (n = 0; n < tsfg->tsf.count_coords; n++) + tsfg->n_ranges[n] = 0; } static void ts_filter_group_clear(struct ts_filter *tsf) @@ -101,8 +116,9 @@ static struct ts_filter *ts_filter_group_create( tsfg->tsf.count_coords = count_coords; BUG_ON(tsfg->config->attempts <= 0); + BUG_ON(tsfg->config->length < tsfg->config->threshold); - tsfg->samples[0] = kmalloc((2 + count_coords) * sizeof(int) * + tsfg->samples[0] = kmalloc(count_coords * sizeof(int) * tsfg->config->length, GFP_KERNEL); if (!tsfg->samples[0]) { kfree(tsfg); @@ -110,10 +126,16 @@ static struct ts_filter *ts_filter_group_create( } for (i = 1; i < count_coords; ++i) tsfg->samples[i] = tsfg->samples[0] + i * tsfg->config->length; - tsfg->sorted_samples = tsfg->samples[0] + count_coords * - tsfg->config->length; - tsfg->group_size = tsfg->samples[0] + (1 + count_coords) * - tsfg->config->length; + + tsfg->ranges[0] = kmalloc(count_coords * sizeof(struct coord_range) * + tsfg->config->length, GFP_KERNEL); + if (!tsfg->ranges[0]) { + kfree(tsfg->samples[0]); + kfree(tsfg); + return NULL; + } + for (i = 1; i < count_coords; ++i) + tsfg->ranges[i] = tsfg->ranges[0] + i * tsfg->config->length; ts_filter_group_clear_internal(tsfg, tsfg->config->attempts); @@ -128,77 +150,90 @@ static void ts_filter_group_destroy(struct ts_filter *tsf) { struct ts_filter_group *tsfg = ts_filter_to_filter_group(tsf); - kfree(tsfg->samples[0]); /* first guy has pointer from kmalloc */ + kfree(tsfg->samples[0]); + kfree(tsfg->ranges[0]); kfree(tsf); } -static int int_cmp(const void *_a, const void *_b) -{ - const int *a = _a; - const int *b = _b; +static void ts_filter_group_prepare_next(struct ts_filter *tsf); - if (*a > *b) - return 1; - if (*a < *b) - return -1; - return 0; -} +#define MIN(a, b) ((a) < (b) ? (a) : (b)) +#define MAX(a, b) ((a) > (b) ? (a) : (b)) +#define IN_RANGE(c, r) ((c) >= (r).min - tsfg->config->close_enough && \ + (c) <= (r).max + tsfg->config->close_enough) -static void ts_filter_group_prepare_next(struct ts_filter *tsf); +static void delete_spot(struct coord_range *v, int n, int size) +{ + int i; + for (i = n; i < size - 1; ++i) + v[i] = v[i + 1]; +} static int ts_filter_group_process(struct ts_filter *tsf, int *coords) { struct ts_filter_group *tsfg = ts_filter_to_filter_group(tsf); int n; - int i; + int j; BUG_ON(tsfg->N >= tsfg->config->length); BUG_ON(tsfg->ready); - for (n = 0; n < tsf->count_coords; n++) - tsfg->samples[n][tsfg->N] = coords[n]; + for (n = 0; n < tsfg->tsf.count_coords; n++) { + int i; + struct coord_range *range = tsfg->ranges[n]; + int *n_ranges = &tsfg->n_ranges[n]; + int found = 0; - if (++tsfg->N < tsfg->config->length) - return 0; /* We need more samples. */ + tsfg->samples[n][tsfg->N] = coords[n]; - for (n = 0; n < tsfg->tsf.count_coords; n++) { - int *v = tsfg->sorted_samples; - int ngroups = 0; - int best_size; - int best_idx = 0; - int idx = 0; - - memcpy(v, tsfg->samples[n], tsfg->N * sizeof(int)); - /* - * FIXME: Remove this sort call. We already have the - * algorithm for this modification. The filter will - * need less points (about half) if there is not a - * lot of noise. Right now we are doing a constant - * amount of work no matter how much noise we are - * dealing with. - */ - sort(v, tsfg->N, sizeof(int), int_cmp, NULL); - - tsfg->group_size[0] = 1; - for (i = 1; i < tsfg->N; ++i) { - if (v[i] - v[i - 1] <= tsfg->config->close_enough) - tsfg->group_size[ngroups]++; - else - tsfg->group_size[++ngroups] = 1; + for (i = 0; i < *n_ranges; ++i) { + if (IN_RANGE(coords[n], range[i])) { + range[i].min = MIN(range[i].min, coords[n]); + range[i].max = MAX(range[i].max, coords[n]); + range[i].N++; + found = 1; + break; + } else if (coords[n] <= range[i].min) + break; /* We need to insert a range. */ } - ngroups++; - - best_size = tsfg->group_size[0]; - for (i = 1; i < ngroups; i++) { - idx += tsfg->group_size[i - 1]; - if (best_size < tsfg->group_size[i]) { - best_size = tsfg->group_size[i]; - best_idx = idx; + if (found) { /* We might need to melt ranges. */ + if (i && range[i - 1].max + tsfg->config->close_enough + >= range[i].min) { + BUG_ON(range[i - 1].max >= range[i].max); + range[i - 1].max = range[i].max; + range[i - 1].N += range[i].N; + delete_spot(range, i, *n_ranges); + (*n_ranges)--; + i--; + } + if (i < *n_ranges - 1 && range[i + 1].min - + tsfg->config->close_enough <= range[i].max) { + range[i].max = range[i + 1].max; + range[i].N += range[i + 1].N; + delete_spot(range, i + 1, *n_ranges); + (*n_ranges)--; } + } else { + BUG_ON((*n_ranges) >= tsfg->config->length); + (*n_ranges)++; + for (j = *n_ranges - 1; j > i; --j) + range[j] = range[j - 1]; + range[i].N = 1; + range[i].min = coords[n]; + range[i].max = coords[n]; } + } - if (best_size < tsfg->config->threshold) { - /* This set is not good enough for us. */ + if (++tsfg->N < tsfg->config->length) + return 0; + + for (n = 0; n < tsfg->tsf.count_coords; ++n) { + int best = 0; + for (j = 1; j < tsfg->n_ranges[n]; ++j) + if (tsfg->ranges[n][best].N < tsfg->ranges[n][j].N) + best = j; + if (tsfg->ranges[n][best].N < tsfg->config->threshold) { + /* This set of points is not good enough for us. */ if (--tsfg->tries_left) { ts_filter_group_clear_internal (tsfg, tsfg->tries_left); @@ -207,9 +242,8 @@ static int ts_filter_group_process(struct ts_filter *tsf, int *coords) } return 1; /* We give up: error. */ } - - tsfg->range_min[n] = v[best_idx]; - tsfg->range_max[n] = v[best_idx + best_size - 1]; + tsfg->range_min[n] = tsfg->ranges[n][best].min; + tsfg->range_max[n] = tsfg->ranges[n][best].max; } ts_filter_group_prepare_next(tsf); -- cgit v1.2.3 From fa5743d920385c2cf344bb1a0b964af8a9511d85 Mon Sep 17 00:00:00 2001 From: Nelson Castillo Date: Thu, 24 Sep 2009 17:37:14 -0500 Subject: Fix small typo s/though/thought/ Reported-by: Rask Ingemann Lambertsen Signed-off-by: Nelson Castillo --- drivers/input/touchscreen/ts_filter_group.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'drivers') diff --git a/drivers/input/touchscreen/ts_filter_group.c b/drivers/input/touchscreen/ts_filter_group.c index 93f8fc690e4..722e8dfbdae 100644 --- a/drivers/input/touchscreen/ts_filter_group.c +++ b/drivers/input/touchscreen/ts_filter_group.c @@ -21,7 +21,7 @@ * This filter is useful to reject samples that are not reliable. We consider * that a sample is not reliable if it deviates form the Majority. * This filter mixes information from all the available dimensions. It means - * that for two dimensions we draw a rectangle where the though-to-be good + * that for two dimensions we draw a rectangle where the thought-to-be good * points can be found. * * The implementation would be more efficient with a double-linked list but -- cgit v1.2.3