diff options
-rw-r--r-- | arch/arm/configs/gta02-moredrivers-defconfig | 1 | ||||
-rw-r--r-- | arch/arm/configs/gta02-packaging-defconfig | 1 | ||||
-rw-r--r-- | arch/arm/mach-s3c2440/mach-gta02.c | 9 | ||||
-rw-r--r-- | drivers/input/touchscreen/Kconfig | 19 | ||||
-rw-r--r-- | drivers/input/touchscreen/Makefile | 2 | ||||
-rw-r--r-- | drivers/input/touchscreen/s3c2410_ts.c | 6 | ||||
-rw-r--r-- | drivers/input/touchscreen/ts_filter.c | 20 | ||||
-rw-r--r-- | drivers/input/touchscreen/ts_filter_group.c | 6 | ||||
-rw-r--r-- | drivers/input/touchscreen/ts_filter_linear.c | 178 | ||||
-rw-r--r-- | drivers/input/touchscreen/ts_filter_mean.c | 6 | ||||
-rw-r--r-- | drivers/input/touchscreen/ts_filter_median.c | 6 | ||||
-rw-r--r-- | drivers/mmc/core/core.c | 8 | ||||
-rw-r--r-- | include/linux/ts_filter.h | 16 | ||||
-rw-r--r-- | include/linux/ts_filter_linear.h | 64 |
14 files changed, 318 insertions, 24 deletions
diff --git a/arch/arm/configs/gta02-moredrivers-defconfig b/arch/arm/configs/gta02-moredrivers-defconfig index 0d67185a2b3..9294b536473 100644 --- a/arch/arm/configs/gta02-moredrivers-defconfig +++ b/arch/arm/configs/gta02-moredrivers-defconfig @@ -983,6 +983,7 @@ CONFIG_TOUCHSCREEN_FILTER=y CONFIG_TOUCHSCREEN_FILTER_GROUP=y CONFIG_TOUCHSCREEN_FILTER_MEDIAN=y CONFIG_TOUCHSCREEN_FILTER_MEAN=y +CONFIG_TOUCHSCREEN_FILTER_LINEAR=y # CONFIG_TOUCHSCREEN_ADS7846 is not set # CONFIG_TOUCHSCREEN_FUJITSU is not set CONFIG_TOUCHSCREEN_S3C2410=y diff --git a/arch/arm/configs/gta02-packaging-defconfig b/arch/arm/configs/gta02-packaging-defconfig index 0f8ee7e2b60..02560223722 100644 --- a/arch/arm/configs/gta02-packaging-defconfig +++ b/arch/arm/configs/gta02-packaging-defconfig @@ -987,6 +987,7 @@ CONFIG_TOUCHSCREEN_FILTER=y CONFIG_TOUCHSCREEN_FILTER_GROUP=y CONFIG_TOUCHSCREEN_FILTER_MEDIAN=y CONFIG_TOUCHSCREEN_FILTER_MEAN=y +CONFIG_TOUCHSCREEN_FILTER_LINEAR=y # CONFIG_TOUCHSCREEN_ADS7846 is not set # CONFIG_TOUCHSCREEN_FUJITSU is not set CONFIG_TOUCHSCREEN_S3C2410=y diff --git a/arch/arm/mach-s3c2440/mach-gta02.c b/arch/arm/mach-s3c2440/mach-gta02.c index dc0ef0f2a5b..7e70f82bebc 100644 --- a/arch/arm/mach-s3c2440/mach-gta02.c +++ b/arch/arm/mach-s3c2440/mach-gta02.c @@ -103,6 +103,7 @@ #include "../plat-s3c24xx/neo1973_pm_gps.h" +#include <linux/ts_filter_linear.h> #include <linux/ts_filter_mean.h> #include <linux/ts_filter_median.h> #include <linux/ts_filter_group.h> @@ -1008,6 +1009,12 @@ static struct s3c2410_udc_mach_info gta02_udc_cfg = { /* touchscreen configuration */ +static struct ts_filter_linear_configuration gta02_ts_linear_config = { + .constants = {1, 0, 0, 0, 1, 0, 1}, /* don't modify coords */ + .coord0 = 0, + .coord1 = 1, +}; + static struct ts_filter_group_configuration gta02_ts_group_config = { .extent = 12, .close_enough = 10, @@ -1033,11 +1040,13 @@ static struct s3c2410_ts_mach_info gta02_ts_cfg = { [0] = &ts_filter_group_api, [1] = &ts_filter_median_api, [2] = &ts_filter_mean_api, + [3] = &ts_filter_linear_api, }, .filter_config = { [0] = >a02_ts_group_config, [1] = >a02_ts_median_config, [2] = >a02_ts_mean_config, + [3] = >a02_ts_linear_config, }, }; diff --git a/drivers/input/touchscreen/Kconfig b/drivers/input/touchscreen/Kconfig index a0f8599a5b2..5db7a67d5b2 100644 --- a/drivers/input/touchscreen/Kconfig +++ b/drivers/input/touchscreen/Kconfig @@ -29,7 +29,6 @@ config TOUCHSCREEN_FILTER_GROUP Say Y here if you want to use the Group touchscreen filter, it avoids using atypical samples. - config TOUCHSCREEN_FILTER_MEDIAN bool "Median Average Touchscreen Filter" depends on INPUT_TOUCHSCREEN && TOUCHSCREEN_FILTER @@ -46,6 +45,14 @@ config TOUCHSCREEN_FILTER_MEAN Say Y here if you want to use the Mean touchscreen filter, it can further improve decent quality data by removing jitter +config TOUCHSCREEN_FILTER_LINEAR + bool "Linear Touchscreen Filter" + depends on INPUT_TOUCHSCREEN && TOUCHSCREEN_FILTER + default Y + help + Say Y here if you want to use the Mean touchscreen filter, it + enables the use of calibration data for the touchscreen. + endif config TOUCHSCREEN_ADS7846 @@ -432,5 +439,15 @@ config TOUCHSCREEN_TOUCHIT213 To compile this driver as a module, choose M here: the module will be called touchit213. +config TOUCHSCREEN_PCAP7200 + tristate "EETI Projected capacitive touchscreen controller" + help + Say Y here if you have the EETI PCAP7200 touchscreen + controller chip in your system. + + If unsure, say N. + + To compile this driver as a module, choose M here: the + module will be called pcap7200. endif diff --git a/drivers/input/touchscreen/Makefile b/drivers/input/touchscreen/Makefile index 9a6162cecc5..b12b0475c9f 100644 --- a/drivers/input/touchscreen/Makefile +++ b/drivers/input/touchscreen/Makefile @@ -34,5 +34,7 @@ obj-$(CONFIG_TOUCHSCREEN_WM97XX_MAINSTONE) += mainstone-wm97xx.o obj-$(CONFIG_TOUCHSCREEN_S3C2410) += s3c2410_ts.o obj-$(CONFIG_TOUCHSCREEN_FILTER) += ts_filter.o obj-$(CONFIG_TOUCHSCREEN_FILTER_GROUP) += ts_filter_group.o +obj-$(CONFIG_TOUCHSCREEN_FILTER_LINEAR) += ts_filter_linear.o obj-$(CONFIG_TOUCHSCREEN_FILTER_MEDIAN) += ts_filter_median.o obj-$(CONFIG_TOUCHSCREEN_FILTER_MEAN) += ts_filter_mean.o +obj-$(CONFIG_TOUCHSCREEN_PCAP7200) += pcap7200_ts.o diff --git a/drivers/input/touchscreen/s3c2410_ts.c b/drivers/input/touchscreen/s3c2410_ts.c index 4159adaec7c..bc9b410f670 100644 --- a/drivers/input/touchscreen/s3c2410_ts.c +++ b/drivers/input/touchscreen/s3c2410_ts.c @@ -435,7 +435,7 @@ static int __init s3c2410ts_probe(struct platform_device *pdev) /* create the filter chain set up for the 2 coordinates we produce */ ret = ts_filter_create_chain( - (struct ts_filter_api **)&info->filter_sequence, + pdev, (struct ts_filter_api **)&info->filter_sequence, (void *)&info->filter_config, ts.tsf, ARRAY_SIZE(ts.coords)); if (ret) dev_info(&pdev->dev, "%d filter(s) initialized\n", ret); @@ -484,7 +484,7 @@ bail5: bail4: disable_irq(IRQ_ADC); bail3: - ts_filter_destroy_chain(ts.tsf); + ts_filter_destroy_chain(pdev, ts.tsf); kfifo_free(ts.event_fifo); bail2: input_unregister_device(ts.dev); @@ -511,7 +511,7 @@ static int s3c2410ts_remove(struct platform_device *pdev) input_unregister_device(ts.dev); iounmap(base_addr); - ts_filter_destroy_chain(ts.tsf); + ts_filter_destroy_chain(pdev, ts.tsf); kfifo_free(ts.event_fifo); diff --git a/drivers/input/touchscreen/ts_filter.c b/drivers/input/touchscreen/ts_filter.c index 4c650a5c66f..15083882e1c 100644 --- a/drivers/input/touchscreen/ts_filter.c +++ b/drivers/input/touchscreen/ts_filter.c @@ -20,8 +20,9 @@ #include <linux/device.h> #include <linux/ts_filter.h> -int ts_filter_create_chain(struct ts_filter_api **api, void **config, - struct ts_filter **list, int count_coords) +int ts_filter_create_chain(struct platform_device *pdev, + struct ts_filter_api **api, void **config, + struct ts_filter **list, int count_coords) { int count = 0; struct ts_filter *last = NULL; @@ -29,13 +30,13 @@ int ts_filter_create_chain(struct ts_filter_api **api, void **config, if (!api) return 0; - while (*api && (count < MAX_TS_FILTER_CHAIN)) { - *list = ((*api)->create)(*config++, count_coords); + while (*api && count < MAX_TS_FILTER_CHAIN) { + *list = ((*api)->create)(pdev, *config++, count_coords); if (!*list) { printk(KERN_ERR "Filter %d failed init\n", count); return count; } - (*list)->api = (struct ts_filter_api *)*api++; + (*list)->api = *api++; if (last) last->next = *list; last = *list; @@ -47,12 +48,15 @@ int ts_filter_create_chain(struct ts_filter_api **api, void **config, } EXPORT_SYMBOL_GPL(ts_filter_create_chain); -void ts_filter_destroy_chain(struct ts_filter **list) +void ts_filter_destroy_chain(struct platform_device *pdev, + struct ts_filter **list) { struct ts_filter **first; + int count = 0; + first = list; - while (*list) { - ((*list)->api->destroy)(*list); + while (*list && count++ < MAX_TS_FILTER_CHAIN) { + ((*list)->api->destroy)(pdev, *list); list++; } *first = NULL; diff --git a/drivers/input/touchscreen/ts_filter_group.c b/drivers/input/touchscreen/ts_filter_group.c index 250613f9345..80e6677d0cf 100644 --- a/drivers/input/touchscreen/ts_filter_group.c +++ b/drivers/input/touchscreen/ts_filter_group.c @@ -59,7 +59,8 @@ static void ts_filter_group_clear(struct ts_filter *tsf) (tsf->next->api->clear)(tsf->next); } -static struct ts_filter *ts_filter_group_create(void *conf, int count_coords) +static struct ts_filter *ts_filter_group_create(struct platform_device *pdev, + void *conf, int count_coords) { struct ts_filter_group *tsfg; int i; @@ -97,7 +98,8 @@ static struct ts_filter *ts_filter_group_create(void *conf, int count_coords) return &tsfg->tsf; } -static void ts_filter_group_destroy(struct ts_filter *tsf) +static void ts_filter_group_destroy(struct platform_device *pdev, + struct ts_filter *tsf) { struct ts_filter_group *tsfg = (struct ts_filter_group *)tsf; diff --git a/drivers/input/touchscreen/ts_filter_linear.c b/drivers/input/touchscreen/ts_filter_linear.c new file mode 100644 index 00000000000..4803e17ae49 --- /dev/null +++ b/drivers/input/touchscreen/ts_filter_linear.c @@ -0,0 +1,178 @@ +/* + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; version 2 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * 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 by Openmoko, Inc. + * Author: Nelson Castillo <arhuaco@freaks-unidos.net> + * All rights reserved. + * + * Linearly scale touchscreen values. + * + * Expose the TS_FILTER_LINEAR_NCONSTANTS for the linear transformation + * using sysfs. + * + */ + +#include <linux/ts_filter_linear.h> +#include <linux/kernel.h> +#include <linux/slab.h> +#include <linux/string.h> + + +/* + * sysfs functions + */ + + +static ssize_t const_attr_show(struct kobject *kobj, + struct attribute *attr, + char *buf) +{ + struct const_attribute *a = to_const_attr(attr); + + return a->show(to_const_obj(kobj), a, buf); +} + +static ssize_t const_attr_store(struct kobject *kobj, + struct attribute *attr, + const char *buf, size_t len) +{ + struct const_attribute *a = to_const_attr(attr); + + return a->store(to_const_obj(kobj), a, buf, len); +} + +static struct sysfs_ops const_sysfs_ops = { + .show = const_attr_show, + .store = const_attr_store, +}; + +static void const_release(struct kobject *kobj) +{ + kfree(to_const_obj(kobj)->tsfl); +} + +static ssize_t const_show(struct const_obj *obj, struct const_attribute *attr, + char *buf) +{ + int who; + + sscanf(attr->attr.name, "%d", &who); + return sprintf(buf, "%d\n", obj->tsfl->constants[who]); +} + +static ssize_t const_store(struct const_obj *obj, struct const_attribute *attr, + const char *buf, size_t count) +{ + int who; + + sscanf(attr->attr.name, "%d", &who); + sscanf(buf, "%d", &obj->tsfl->constants[who]); + return count; +} + +/* + * filter functions + */ + +static struct ts_filter *ts_filter_linear_create(struct platform_device *pdev, + void *conf, int count_coords) +{ + struct ts_filter_linear *tsfl; + int i; + int ret; + + tsfl = kzalloc(sizeof(struct ts_filter_linear), GFP_KERNEL); + if (!tsfl) + return NULL; + + tsfl->config = (struct ts_filter_linear_configuration *)conf; + tsfl->tsf.count_coords = count_coords; + + for (i = 0; i < TS_FILTER_LINEAR_NCONSTANTS; ++i) { + tsfl->constants[i] = tsfl->config->constants[i]; + + /* sysfs */ + sprintf(tsfl->attr_names[i], "%d", i); + tsfl->kattrs[i].attr.name = tsfl->attr_names[i]; + tsfl->kattrs[i].attr.mode = 0666; + tsfl->kattrs[i].show = const_show; + tsfl->kattrs[i].store = const_store; + tsfl->attrs[i] = &tsfl->kattrs[i].attr; + } + tsfl->attrs[i] = NULL; + + tsfl->const_ktype.sysfs_ops = &const_sysfs_ops; + tsfl->const_ktype.release = const_release; + tsfl->const_ktype.default_attrs = tsfl->attrs; + tsfl->c_obj.tsfl = tsfl; /* kernel frees tsfl in const_release */ + + /* TODO: /sys/ts-calibration is not OK */ + ret = kobject_init_and_add(&tsfl->c_obj.kobj, &tsfl->const_ktype, + &pdev->dev.kobj, "calibration"); + if (ret) { + kobject_put(&tsfl->c_obj.kobj); + return NULL; + } + + printk(KERN_INFO" Created Linear ts filter depth %d\n", count_coords); + + return &tsfl->tsf; +} + +static void ts_filter_linear_destroy(struct platform_device *pdev, + struct ts_filter *tsf) +{ + struct ts_filter_linear *tsfl = (struct ts_filter_linear *)tsf; + + /* kernel frees tsfl in const_release */ + kobject_put(&tsfl->c_obj.kobj); +} + +static void ts_filter_linear_clear(struct ts_filter *tsf) +{ + if (tsf->next) /* chain */ + (tsf->next->api->clear)(tsf->next); +} + + +static void ts_filter_linear_scale(struct ts_filter *tsf, int *coords) +{ + struct ts_filter_linear *tsfl = (struct ts_filter_linear *)tsf; + int *k = tsfl->constants; + int c0 = coords[tsfl->config->coord0]; + int c1 = coords[tsfl->config->coord1]; + + coords[tsfl->config->coord0] = (k[2] + k[0] * c0 + k[1] * c1) / k[6]; + coords[tsfl->config->coord1] = (k[5] + k[3] * c0 + k[4] * c1) / k[6]; + + if (tsf->next) + (tsf->next->api->scale)(tsf->next, coords); +} + +static int ts_filter_linear_process(struct ts_filter *tsf, int *coords) +{ + if (tsf->next) + return (tsf->next->api->process)(tsf->next, coords); + + return 1; +} + +struct ts_filter_api ts_filter_linear_api = { + .create = ts_filter_linear_create, + .destroy = ts_filter_linear_destroy, + .clear = ts_filter_linear_clear, + .process = ts_filter_linear_process, + .scale = ts_filter_linear_scale, +}; diff --git a/drivers/input/touchscreen/ts_filter_mean.c b/drivers/input/touchscreen/ts_filter_mean.c index a2f1748a686..a7b4a5aac6f 100644 --- a/drivers/input/touchscreen/ts_filter_mean.c +++ b/drivers/input/touchscreen/ts_filter_mean.c @@ -56,7 +56,8 @@ static void ts_filter_mean_clear(struct ts_filter *tsf) (tsf->next->api->clear)(tsf->next); } -static struct ts_filter *ts_filter_mean_create(void *config, int count_coords) +static struct ts_filter *ts_filter_mean_create(struct platform_device *pdev, + void *config, int count_coords) { int *p; int n; @@ -96,7 +97,8 @@ static struct ts_filter *ts_filter_mean_create(void *config, int count_coords) return &tsfs->tsf; } -static void ts_filter_mean_destroy(struct ts_filter *tsf) +static void ts_filter_mean_destroy(struct platform_device *pdev, + struct ts_filter *tsf) { struct ts_filter_mean *tsfs = (struct ts_filter_mean *)tsf; diff --git a/drivers/input/touchscreen/ts_filter_median.c b/drivers/input/touchscreen/ts_filter_median.c index 67dd3febd55..883ab06bff0 100644 --- a/drivers/input/touchscreen/ts_filter_median.c +++ b/drivers/input/touchscreen/ts_filter_median.c @@ -81,7 +81,8 @@ static void ts_filter_median_clear(struct ts_filter *tsf) (tsf->next->api->clear)(tsf->next); } -static struct ts_filter *ts_filter_median_create(void * conf, int count_coords) +static struct ts_filter *ts_filter_median_create(struct platform_device *pdev, + void *conf, int count_coords) { int *p; int n; @@ -120,7 +121,8 @@ static struct ts_filter *ts_filter_median_create(void * conf, int count_coords) return &tsfm->tsf; } -static void ts_filter_median_destroy(struct ts_filter *tsf) +static void ts_filter_median_destroy(struct platform_device *pdev, + struct ts_filter *tsf) { struct ts_filter_median *tsfm = (struct ts_filter_median *)tsf; diff --git a/drivers/mmc/core/core.c b/drivers/mmc/core/core.c index b76667e36e8..56988ff4732 100644 --- a/drivers/mmc/core/core.c +++ b/drivers/mmc/core/core.c @@ -496,7 +496,13 @@ void mmc_set_timing(struct mmc_host *host, unsigned int timing) */ static void mmc_power_up(struct mmc_host *host) { - int bit = fls(host->ocr_avail) - 1; + int bit; + + /* If ocr is set, we use it */ + if (host->ocr) + bit = ffs(host->ocr) - 1; + else + bit = fls(host->ocr_avail) - 1; host->ios.vdd = bit; if (mmc_host_is_spi(host)) { diff --git a/include/linux/ts_filter.h b/include/linux/ts_filter.h index 715f1badbf4..167104482dd 100644 --- a/include/linux/ts_filter.h +++ b/include/linux/ts_filter.h @@ -7,6 +7,8 @@ * (c) 2008 Andy Green <andy@openmoko.com> */ +#include <linux/platform_device.h> + #define MAX_TS_FILTER_CHAIN 4 /* max filters you can chain up */ #define MAX_TS_FILTER_COORDS 3 /* X, Y and Z (pressure) */ @@ -15,8 +17,9 @@ struct ts_filter; /* operations that a filter can perform */ struct ts_filter_api { - struct ts_filter * (*create)(void *config, int count_coords); - void (*destroy)(struct ts_filter *filter); + struct ts_filter * (*create)(struct platform_device *pdev, void *config, + int count_coords); + void (*destroy)(struct platform_device *pdev, struct ts_filter *filter); void (*clear)(struct ts_filter *filter); int (*process)(struct ts_filter *filter, int *coords); void (*scale)(struct ts_filter *filter, int *coords); @@ -41,10 +44,13 @@ struct ts_filter { * array and fills in ->next pointers to create the chain */ -extern int ts_filter_create_chain(struct ts_filter_api **api, void **config, - struct ts_filter **list, int count_coords); +extern int ts_filter_create_chain(struct platform_device *pdev, + struct ts_filter_api **api, void **config, + struct ts_filter **list, int count_coords); /* helper to destroy a whole chain from the list of filter pointers */ -extern void ts_filter_destroy_chain(struct ts_filter **list); +extern void ts_filter_destroy_chain(struct platform_device *pdev, + struct ts_filter **list); + #endif diff --git a/include/linux/ts_filter_linear.h b/include/linux/ts_filter_linear.h new file mode 100644 index 00000000000..dab53907a90 --- /dev/null +++ b/include/linux/ts_filter_linear.h @@ -0,0 +1,64 @@ +#ifndef __TS_FILTER_LINEAR_H__ +#define __TS_FILTER_LINEAR_H__ + +#include <linux/ts_filter.h> +#include <linux/kobject.h> + +/* + * touchscreen linear filter. + * + * Copyright (C) 2008 by Openmoko, Inc. + * Author: Nelson Castillo <arhuaco@freaks-unidos.net> + * + */ + +#define TS_FILTER_LINEAR_NCONSTANTS 7 + +/* sysfs */ + +struct ts_filter_linear; + +struct const_obj { + struct ts_filter_linear *tsfl; + struct kobject kobj; +}; + +#define to_const_obj(x) container_of(x, struct const_obj, kobj) + +struct const_attribute { + struct attribute attr; + ssize_t (*show)(struct const_obj *const, struct const_attribute *attr, + char *buf); + ssize_t (*store)(struct const_obj *const, struct const_attribute *attr, + const char *buf, size_t count); +}; + +#define to_const_attr(x) container_of(x, struct const_attribute, attr) + +/* filter configuration */ + +struct ts_filter_linear_configuration { + int constants[TS_FILTER_LINEAR_NCONSTANTS]; + int coord0; + int coord1; +}; + +/* the filter */ + +struct ts_filter_linear { + struct ts_filter tsf; + struct ts_filter_linear_configuration *config; + + int constants[TS_FILTER_LINEAR_NCONSTANTS]; + + /* sysfs */ + struct const_obj c_obj; + struct kobj_type const_ktype; + struct const_attribute kattrs[TS_FILTER_LINEAR_NCONSTANTS]; + struct attribute *attrs[TS_FILTER_LINEAR_NCONSTANTS + 1]; + char attr_names[TS_FILTER_LINEAR_NCONSTANTS][2]; +}; + +extern struct ts_filter_api ts_filter_linear_api; + +#endif |