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(-) 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 9cf83000da2611923c9c250f6e14fd09dae45df9 Mon Sep 17 00:00:00 2001 From: Nelson Castillo Date: Tue, 22 Sep 2009 05:22:57 -0500 Subject: S3C: ADC: Fix lines with more than 80 chars in adc.h Small cleanup. Signed-off-by: Nelson Castillo [ben-linux@fluff.org: rewrote subject] Signed-off-by: Ben Dooks --- arch/arm/plat-s3c/include/plat/adc.h | 9 +++++---- 1 file changed, 5 insertions(+), 4 deletions(-) diff --git a/arch/arm/plat-s3c/include/plat/adc.h b/arch/arm/plat-s3c/include/plat/adc.h index 43df2a404b0..ef92e50ac0a 100644 --- a/arch/arm/plat-s3c/include/plat/adc.h +++ b/arch/arm/plat-s3c/include/plat/adc.h @@ -19,10 +19,11 @@ struct s3c_adc_client; extern int s3c_adc_start(struct s3c_adc_client *client, unsigned int channel, unsigned int nr_samples); -extern struct s3c_adc_client *s3c_adc_register(struct platform_device *pdev, - void (*select)(unsigned selected), - void (*conv)(unsigned d0, unsigned d1), - unsigned int is_ts); +extern struct s3c_adc_client * + s3c_adc_register(struct platform_device *pdev, + void (*select)(unsigned selected), + void (*conv)(unsigned d0, unsigned d1), + unsigned int is_ts); extern void s3c_adc_release(struct s3c_adc_client *client); -- cgit v1.2.3 From f4ad756aceabef95fea74609de81375ee8efc6c5 Mon Sep 17 00:00:00 2001 From: Nelson Castillo Date: Tue, 22 Sep 2009 05:23:04 -0500 Subject: S3C: ADC: Expose number of remaining conversions to convert callback This patch allow us to efficiently modify the number of remaining conversions from the client side. This us useful when we do not know in advance how many conversions we will need or when we need to cancel pending conversions. This change is simple enough to be compatible with existing code that can just define the new pointer in the callback and ignore it. Sample usage: http://tinyurl.com/s3c2410-ts-c (function stylus_adc_action). Signed-off-by: Nelson Castillo Signed-off-by: Ben Dooks --- arch/arm/plat-s3c/include/plat/adc.h | 3 ++- arch/arm/plat-s3c24xx/adc.c | 11 +++++++---- 2 files changed, 9 insertions(+), 5 deletions(-) diff --git a/arch/arm/plat-s3c/include/plat/adc.h b/arch/arm/plat-s3c/include/plat/adc.h index ef92e50ac0a..d847bd476b6 100644 --- a/arch/arm/plat-s3c/include/plat/adc.h +++ b/arch/arm/plat-s3c/include/plat/adc.h @@ -22,7 +22,8 @@ extern int s3c_adc_start(struct s3c_adc_client *client, extern struct s3c_adc_client * s3c_adc_register(struct platform_device *pdev, void (*select)(unsigned selected), - void (*conv)(unsigned d0, unsigned d1), + void (*conv)(unsigned d0, unsigned d1, + unsigned *samples_left), unsigned int is_ts); extern void s3c_adc_release(struct s3c_adc_client *client); diff --git a/arch/arm/plat-s3c24xx/adc.c b/arch/arm/plat-s3c24xx/adc.c index 9a5c767e0a4..03429b2a27f 100644 --- a/arch/arm/plat-s3c24xx/adc.c +++ b/arch/arm/plat-s3c24xx/adc.c @@ -45,7 +45,8 @@ struct s3c_adc_client { unsigned char channel; void (*select_cb)(unsigned selected); - void (*convert_cb)(unsigned val1, unsigned val2); + void (*convert_cb)(unsigned val1, unsigned val2, + unsigned *samples_left); }; struct adc_device { @@ -158,7 +159,8 @@ static void s3c_adc_default_select(unsigned select) struct s3c_adc_client *s3c_adc_register(struct platform_device *pdev, void (*select)(unsigned int selected), - void (*conv)(unsigned d0, unsigned d1), + void (*conv)(unsigned d0, unsigned d1, + unsigned *samples_left), unsigned int is_ts) { struct s3c_adc_client *client; @@ -210,9 +212,10 @@ static irqreturn_t s3c_adc_irq(int irq, void *pw) data1 = readl(adc->regs + S3C2410_ADCDAT1); adc_dbg(adc, "read %d: 0x%04x, 0x%04x\n", client->nr_samples, data0, data1); - (client->convert_cb)(data0 & 0x3ff, data1 & 0x3ff); + client->nr_samples--; + (client->convert_cb)(data0 & 0x3ff, data1 & 0x3ff, &client->nr_samples); - if (--client->nr_samples > 0) { + if (client->nr_samples > 0) { /* fire another conversion for this */ client->select_cb(1); -- cgit v1.2.3 From 16e3d48d8ff84d279483b237c1e509ff1388eca2 Mon Sep 17 00:00:00 2001 From: Vasily Khoruzhick Date: Tue, 22 Sep 2009 05:23:12 -0500 Subject: s3c24xx: introduce s3c-adc delay Without this patch we cannot make the s3c2410/s3c2440 touchscreen driver work. Is this delay device-dependant? Is there a better way to do this? We specify the delay value (S3C2410_ADCDLY). Signed-off-by: Vasily Khoruzhick Signed-off-by: Nelson Castillo --- arch/arm/plat-s3c24xx/adc.c | 4 ++++ 1 file changed, 4 insertions(+) diff --git a/arch/arm/plat-s3c24xx/adc.c b/arch/arm/plat-s3c24xx/adc.c index 03429b2a27f..a9eec95f70d 100644 --- a/arch/arm/plat-s3c24xx/adc.c +++ b/arch/arm/plat-s3c24xx/adc.c @@ -58,6 +58,7 @@ struct adc_device { void __iomem *regs; unsigned int prescale; + unsigned int delay; int irq; }; @@ -247,6 +248,7 @@ static int s3c_adc_probe(struct platform_device *pdev) adc->pdev = pdev; adc->prescale = S3C2410_ADCCON_PRSCVL(49); + adc->delay = 0x2710; adc->irq = platform_get_irq(pdev, 1); if (adc->irq <= 0) { @@ -286,6 +288,7 @@ static int s3c_adc_probe(struct platform_device *pdev) writel(adc->prescale | S3C2410_ADCCON_PRSCEN, adc->regs + S3C2410_ADCCON); + writel(adc->delay, adc->regs + S3C2410_ADCDLY); dev_info(dev, "attached adc driver\n"); @@ -341,6 +344,7 @@ static int s3c_adc_resume(struct platform_device *pdev) writel(adc->prescale | S3C2410_ADCCON_PRSCEN, adc->regs + S3C2410_ADCCON); + writel(adc->delay, adc->regs + S3C2410_ADCDLY); return 0; } -- 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 --- arch/arm/configs/gta01_moredrivers_defconfig | 2 +- arch/arm/configs/gta02_micro_defconfig | 2 +- arch/arm/configs/gta02_moredrivers_defconfig | 2 +- arch/arm/configs/gta02_packaging_defconfig | 2 +- arch/arm/mach-s3c2410/mach-gta01.c | 4 + arch/arm/mach-s3c2442/mach-gta02.c | 3 + arch/arm/plat-s3c24xx/adc.c | 9 ++ arch/arm/plat-s3c24xx/devs.c | 1 + drivers/input/touchscreen/s3c2410_ts.c | 136 ++++++++++----------------- 9 files changed, 70 insertions(+), 91 deletions(-) diff --git a/arch/arm/configs/gta01_moredrivers_defconfig b/arch/arm/configs/gta01_moredrivers_defconfig index 36d2b170b52..0ed35d8bd1b 100644 --- a/arch/arm/configs/gta01_moredrivers_defconfig +++ b/arch/arm/configs/gta01_moredrivers_defconfig @@ -180,7 +180,7 @@ CONFIG_S3C2410_CLOCK=y CONFIG_S3C24XX_GPIO_EXTRA=0 CONFIG_S3C2410_DMA=y # CONFIG_S3C2410_DMA_DEBUG is not set -# CONFIG_S3C24XX_ADC is not set +CONFIG_S3C24XX_ADC=y CONFIG_MACH_NEO1973=y CONFIG_PLAT_S3C=y CONFIG_CPU_LLSERIAL_S3C2410_ONLY=y diff --git a/arch/arm/configs/gta02_micro_defconfig b/arch/arm/configs/gta02_micro_defconfig index ae30c4b1ddb..6a6ff77ea2c 100644 --- a/arch/arm/configs/gta02_micro_defconfig +++ b/arch/arm/configs/gta02_micro_defconfig @@ -158,7 +158,7 @@ CONFIG_S3C24XX_PWM=y CONFIG_S3C24XX_GPIO_EXTRA=0 CONFIG_S3C2410_DMA=y # CONFIG_S3C2410_DMA_DEBUG is not set -# CONFIG_S3C24XX_ADC is not set +CONFIG_S3C24XX_ADC=y CONFIG_MACH_NEO1973=y CONFIG_PLAT_S3C=y CONFIG_CPU_LLSERIAL_S3C2440_ONLY=y diff --git a/arch/arm/configs/gta02_moredrivers_defconfig b/arch/arm/configs/gta02_moredrivers_defconfig index bd66869f74a..13b41215faa 100644 --- a/arch/arm/configs/gta02_moredrivers_defconfig +++ b/arch/arm/configs/gta02_moredrivers_defconfig @@ -180,7 +180,7 @@ CONFIG_S3C24XX_PWM=y CONFIG_S3C24XX_GPIO_EXTRA=0 CONFIG_S3C2410_DMA=y # CONFIG_S3C2410_DMA_DEBUG is not set -# CONFIG_S3C24XX_ADC is not set +CONFIG_S3C24XX_ADC=y CONFIG_MACH_SMDK=y CONFIG_MACH_NEO1973=y CONFIG_PLAT_S3C=y diff --git a/arch/arm/configs/gta02_packaging_defconfig b/arch/arm/configs/gta02_packaging_defconfig index 15defd28841..03c72d5652b 100644 --- a/arch/arm/configs/gta02_packaging_defconfig +++ b/arch/arm/configs/gta02_packaging_defconfig @@ -180,7 +180,7 @@ CONFIG_S3C24XX_PWM=y CONFIG_S3C24XX_GPIO_EXTRA=0 CONFIG_S3C2410_DMA=y # CONFIG_S3C2410_DMA_DEBUG is not set -# CONFIG_S3C24XX_ADC is not set +CONFIG_S3C24XX_ADC=y CONFIG_MACH_SMDK=y CONFIG_MACH_NEO1973=y CONFIG_PLAT_S3C=y diff --git a/arch/arm/mach-s3c2410/mach-gta01.c b/arch/arm/mach-s3c2410/mach-gta01.c index 8a13a4adcfd..339eb845744 100644 --- a/arch/arm/mach-s3c2410/mach-gta01.c +++ b/arch/arm/mach-s3c2410/mach-gta01.c @@ -993,6 +993,10 @@ static void __init gta01_machine_init(void) printk(KERN_DEBUG "Enabled GSM wakeup IRQ %d (rc=%d)\n", GTA01_IRQ_MODEM, rc); +#ifdef CONFIG_S3C24XX_ADC + platform_device_register(&s3c_device_adc); +#endif + pm_power_off = >a01_power_off; } diff --git a/arch/arm/mach-s3c2442/mach-gta02.c b/arch/arm/mach-s3c2442/mach-gta02.c index e4f052595bd..346c2298b08 100644 --- a/arch/arm/mach-s3c2442/mach-gta02.c +++ b/arch/arm/mach-s3c2442/mach-gta02.c @@ -1717,6 +1717,9 @@ static void __init gta02_machine_init(void) gta02_vibrator_dev.dev.parent = &s3c24xx_pwm_device.dev; platform_device_register(>a02_vibrator_dev); #endif +#ifdef CONFIG_S3C24XX_ADC + platform_device_register(&s3c_device_adc); +#endif } void DEBUG_LED(int n) diff --git a/arch/arm/plat-s3c24xx/adc.c b/arch/arm/plat-s3c24xx/adc.c index a9eec95f70d..9056bcc6c17 100644 --- a/arch/arm/plat-s3c24xx/adc.c +++ b/arch/arm/plat-s3c24xx/adc.c @@ -69,10 +69,19 @@ static LIST_HEAD(adc_pending); #define adc_dbg(_adc, msg...) dev_dbg(&(_adc)->pdev->dev, msg) +#define AUTOPST (S3C2410_ADCTSC_YM_SEN | S3C2410_ADCTSC_YP_SEN | \ + S3C2410_ADCTSC_XP_SEN | S3C2410_ADCTSC_AUTO_PST | \ + S3C2410_ADCTSC_XY_PST(0)) + + static inline void s3c_adc_convert(struct adc_device *adc) { unsigned con = readl(adc->regs + S3C2410_ADCCON); + if (adc->cur->is_ts) + writel(S3C2410_ADCTSC_PULL_UP_DISABLE | AUTOPST, + adc->regs + S3C2410_ADCTSC); + con |= S3C2410_ADCCON_ENABLE_START; writel(con, adc->regs + S3C2410_ADCCON); } diff --git a/arch/arm/plat-s3c24xx/devs.c b/arch/arm/plat-s3c24xx/devs.c index 0fdaa54ada9..eeb95f863ce 100644 --- a/arch/arm/plat-s3c24xx/devs.c +++ b/arch/arm/plat-s3c24xx/devs.c @@ -205,6 +205,7 @@ EXPORT_SYMBOL(s3c_device_nand); struct platform_device s3c_device_ts = { .name = "s3c2410-ts", .id = -1, + .dev.parent = &s3c_device_adc.dev, }; EXPORT_SYMBOL(s3c_device_ts); 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(-) 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(-) 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(-) 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 03ef252d6732527904eeec98849f49a09a515382 Mon Sep 17 00:00:00 2001 From: Nelson Castillo Date: Tue, 22 Sep 2009 05:23:50 -0500 Subject: GTA01: Disable glamo Remove glamo from defconfig. Signed-off-by: Nelson Castillo --- arch/arm/configs/gta01_moredrivers_defconfig | 6 +----- 1 file changed, 1 insertion(+), 5 deletions(-) diff --git a/arch/arm/configs/gta01_moredrivers_defconfig b/arch/arm/configs/gta01_moredrivers_defconfig index 0ed35d8bd1b..411acab046f 100644 --- a/arch/arm/configs/gta01_moredrivers_defconfig +++ b/arch/arm/configs/gta01_moredrivers_defconfig @@ -1192,11 +1192,7 @@ CONFIG_SSB_POSSIBLE=y CONFIG_MFD_PCF50606=y CONFIG_PCF50606_ADC=y CONFIG_PCF50606_GPO=y -CONFIG_MFD_GLAMO=y -CONFIG_MFD_GLAMO_FB=y -CONFIG_MFD_GLAMO_SPI_GPIO=y -CONFIG_MFD_GLAMO_SPI_FB=y -CONFIG_MFD_GLAMO_MCI=y +# CONFIG_MFD_GLAMO is not set # # Multimedia devices -- cgit v1.2.3 From f7c1655ba09cdf316156883ab088f2030a651678 Mon Sep 17 00:00:00 2001 From: Nelson Castillo Date: Wed, 23 Sep 2009 02:01:37 -0500 Subject: Require CONFIG_S3C24XX_ADC for GTA01/GTA02 Select CONFIG_S3C24XX_ADC by defult for GTA01/GTA02. Somebody will hate me if I don't send this patch soon. Signed-off-by: Nelson Castillo --- arch/arm/mach-s3c2410/Kconfig | 1 + arch/arm/mach-s3c2442/Kconfig | 1 + 2 files changed, 2 insertions(+) diff --git a/arch/arm/mach-s3c2410/Kconfig b/arch/arm/mach-s3c2410/Kconfig index f4f7af180aa..02f406bea08 100644 --- a/arch/arm/mach-s3c2410/Kconfig +++ b/arch/arm/mach-s3c2410/Kconfig @@ -155,6 +155,7 @@ config MACH_NEO1973_GTA01 select PCF50606_WATCHDOG select POWER_SUPPLY select BATTERY_GTA01 + select S3C24XX_ADC help Say Y here if you are using the FIC Neo1973 GSM Phone diff --git a/arch/arm/mach-s3c2442/Kconfig b/arch/arm/mach-s3c2442/Kconfig index aa184ba7586..13fb5e190b4 100644 --- a/arch/arm/mach-s3c2442/Kconfig +++ b/arch/arm/mach-s3c2442/Kconfig @@ -36,6 +36,7 @@ config MACH_NEO1973_GTA02 select S3C_PWM select FIQ select S3C_DEV_USB_HOST + select S3C24XX_ADC help Say Y here if you are using the FIC Neo1973 GSM Phone -- cgit v1.2.3 From 9c3fe7498950875215cdd2c3bb6b0bef70570be0 Mon Sep 17 00:00:00 2001 From: Nelson Castillo Date: Wed, 23 Sep 2009 02:44:08 -0500 Subject: Fix wrong commit I'm quite sorry I sent the commit that crashes GTA01. The fix is quite short. Fixing is easier than reverting and fixing conflicts. Signed-off-by: Nelson Castillo --- arch/arm/mach-s3c2410/mach-gta01.c | 5 +---- arch/arm/mach-s3c2442/mach-gta02.c | 4 +--- 2 files changed, 2 insertions(+), 7 deletions(-) diff --git a/arch/arm/mach-s3c2410/mach-gta01.c b/arch/arm/mach-s3c2410/mach-gta01.c index 339eb845744..21726956ff6 100644 --- a/arch/arm/mach-s3c2410/mach-gta01.c +++ b/arch/arm/mach-s3c2410/mach-gta01.c @@ -560,6 +560,7 @@ static struct platform_device *gta01_devices[] __initdata = { &s3c_device_sdi, &s3c_device_usbgadget, &s3c_device_nand, + &s3c_device_adc, &s3c_device_ts, }; @@ -993,10 +994,6 @@ static void __init gta01_machine_init(void) printk(KERN_DEBUG "Enabled GSM wakeup IRQ %d (rc=%d)\n", GTA01_IRQ_MODEM, rc); -#ifdef CONFIG_S3C24XX_ADC - platform_device_register(&s3c_device_adc); -#endif - pm_power_off = >a01_power_off; } diff --git a/arch/arm/mach-s3c2442/mach-gta02.c b/arch/arm/mach-s3c2442/mach-gta02.c index 346c2298b08..380effad4d4 100644 --- a/arch/arm/mach-s3c2442/mach-gta02.c +++ b/arch/arm/mach-s3c2442/mach-gta02.c @@ -1561,6 +1561,7 @@ static struct platform_device *gta02_devices[] __initdata = { &s3c_device_usbgadget, &s3c_device_nand, >a02_nor_flash, + &s3c_device_adc, &s3c24xx_pwm_device, >a02_led_dev, @@ -1717,9 +1718,6 @@ static void __init gta02_machine_init(void) gta02_vibrator_dev.dev.parent = &s3c24xx_pwm_device.dev; platform_device_register(>a02_vibrator_dev); #endif -#ifdef CONFIG_S3C24XX_ADC - platform_device_register(&s3c_device_adc); -#endif } void DEBUG_LED(int n) -- 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(-) 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