From 1f8b2c9d38c132e79e18cc726cf7a40ebdcb56d9 Mon Sep 17 00:00:00 2001 From: Dave Jones Date: Wed, 29 Mar 2006 01:40:04 -0500 Subject: [CPUFREQ] extra debugging in cpufreq_add_dev() Snipped from an otherwise rejected patch by Jan Beulich Signed-off-by: Dave Jones --- drivers/cpufreq/cpufreq.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'drivers') diff --git a/drivers/cpufreq/cpufreq.c b/drivers/cpufreq/cpufreq.c index 9b6ae7dc8b8..f2179ab65c4 100644 --- a/drivers/cpufreq/cpufreq.c +++ b/drivers/cpufreq/cpufreq.c @@ -685,7 +685,7 @@ static int cpufreq_add_dev (struct sys_device * sys_dev) if (!cpu_online(j)) continue; - dprintk("CPU already managed, adding link\n"); + dprintk("CPU %u already managed, adding link\n", j); cpufreq_cpu_get(cpu); cpu_sys_dev = get_cpu_sysdev(j); sysfs_create_link(&cpu_sys_dev->kobj, &policy->kobj, -- cgit v1.2.3-18-g5258 From 87c32271380e630955de365656f67b0a54b75b19 Mon Sep 17 00:00:00 2001 From: Dave Jones Date: Wed, 29 Mar 2006 01:48:37 -0500 Subject: [CPUFREQ] trailing whitespace removal de-jour. Signed-off-by: Dave Jones --- drivers/cpufreq/cpufreq.c | 5 ++--- 1 file changed, 2 insertions(+), 3 deletions(-) (limited to 'drivers') diff --git a/drivers/cpufreq/cpufreq.c b/drivers/cpufreq/cpufreq.c index f2179ab65c4..3d0430741b5 100644 --- a/drivers/cpufreq/cpufreq.c +++ b/drivers/cpufreq/cpufreq.c @@ -695,9 +695,8 @@ static int cpufreq_add_dev (struct sys_device * sys_dev) policy->governor = NULL; /* to assure that the starting sequence is * run in cpufreq_set_policy */ mutex_unlock(&policy->lock); - + /* set default policy */ - ret = cpufreq_set_policy(&new_policy); if (ret) { dprintk("setting policy failed\n"); @@ -707,7 +706,7 @@ static int cpufreq_add_dev (struct sys_device * sys_dev) module_put(cpufreq_driver->owner); dprintk("initialization complete\n"); cpufreq_debug_enable_ratelimit(); - + return 0; -- cgit v1.2.3-18-g5258 From b82fbe6c4232365272bde6f2c3f8fd9dd4dcd73a Mon Sep 17 00:00:00 2001 From: Dave Jones Date: Sat, 1 Apr 2006 22:07:07 -0500 Subject: [CPUFREQ] Remove pointless check in conservative governor. < 0 checks on unsigned variables are pointless. Signed-off-by: Dave Jones --- drivers/cpufreq/cpufreq_conservative.c | 6 ++---- 1 file changed, 2 insertions(+), 4 deletions(-) (limited to 'drivers') diff --git a/drivers/cpufreq/cpufreq_conservative.c b/drivers/cpufreq/cpufreq_conservative.c index 037f6bf4543..e07a35487bd 100644 --- a/drivers/cpufreq/cpufreq_conservative.c +++ b/drivers/cpufreq/cpufreq_conservative.c @@ -176,8 +176,7 @@ static ssize_t store_up_threshold(struct cpufreq_policy *unused, ret = sscanf (buf, "%u", &input); mutex_lock(&dbs_mutex); - if (ret != 1 || input > 100 || input < 0 || - input <= dbs_tuners_ins.down_threshold) { + if (ret != 1 || input > 100 || input <= dbs_tuners_ins.down_threshold) { mutex_unlock(&dbs_mutex); return -EINVAL; } @@ -196,8 +195,7 @@ static ssize_t store_down_threshold(struct cpufreq_policy *unused, ret = sscanf (buf, "%u", &input); mutex_lock(&dbs_mutex); - if (ret != 1 || input > 100 || input < 0 || - input >= dbs_tuners_ins.up_threshold) { + if (ret != 1 || input > 100 || input >= dbs_tuners_ins.up_threshold) { mutex_unlock(&dbs_mutex); return -EINVAL; } -- cgit v1.2.3-18-g5258 From 4c41251e31982002bca0ce7e903c0cc66218c1ec Mon Sep 17 00:00:00 2001 From: Erik Mouw Date: Mon, 3 Apr 2006 14:21:00 +0200 Subject: [CPUFREQ] Update LART site URL Update LART site URL. The LART website moved to http://www.lartmaker.nl/. This patch updates the URL in CpuFreq specific files. Signed-off-by: Erik Mouw Signed-off-by: Dave Jones --- drivers/cpufreq/Kconfig | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'drivers') diff --git a/drivers/cpufreq/Kconfig b/drivers/cpufreq/Kconfig index 60c9be99c6d..2cc71b66231 100644 --- a/drivers/cpufreq/Kconfig +++ b/drivers/cpufreq/Kconfig @@ -99,7 +99,7 @@ config CPU_FREQ_GOV_USERSPACE Enable this cpufreq governor when you either want to set the CPU frequency manually or when an userspace program shall be able to set the CPU dynamically, like on LART - + . For details, take a look at . -- cgit v1.2.3-18-g5258 From 8a1b170898cd827b24cbf02c43c57f8489e9ccce Mon Sep 17 00:00:00 2001 From: Stefan Rompf Date: Wed, 5 Apr 2006 00:39:20 -0400 Subject: Input: wistron - add signature for Amilo M7400 Signed-off-by: Dmitry Torokhov --- drivers/input/misc/wistron_btns.c | 9 +++++++++ 1 file changed, 9 insertions(+) (limited to 'drivers') diff --git a/drivers/input/misc/wistron_btns.c b/drivers/input/misc/wistron_btns.c index 4b415d9b012..6ec05985a14 100644 --- a/drivers/input/misc/wistron_btns.c +++ b/drivers/input/misc/wistron_btns.c @@ -321,6 +321,15 @@ static struct dmi_system_id dmi_ids[] = { }, .driver_data = keymap_fs_amilo_pro_v2000 }, + { + .callback = dmi_matched, + .ident = "Fujitsu-Siemens Amilo M7400", + .matches = { + DMI_MATCH(DMI_SYS_VENDOR, "FUJITSU SIEMENS"), + DMI_MATCH(DMI_PRODUCT_NAME, "AMILO M "), + }, + .driver_data = keymap_fs_amilo_pro_v2000 + }, { .callback = dmi_matched, .ident = "Acer Aspire 1500", -- cgit v1.2.3-18-g5258 From e2aa507a837cbaa376faa3d9f8448ff569d34ccf Mon Sep 17 00:00:00 2001 From: John Reed Riley Date: Wed, 5 Apr 2006 00:40:01 -0400 Subject: Input: wistron - add support for Fujitsu N3510 Signed-off-by: Dmitry Torokhov --- drivers/input/misc/wistron_btns.c | 21 +++++++++++++++++++++ 1 file changed, 21 insertions(+) (limited to 'drivers') diff --git a/drivers/input/misc/wistron_btns.c b/drivers/input/misc/wistron_btns.c index 6ec05985a14..36cd2e07fce 100644 --- a/drivers/input/misc/wistron_btns.c +++ b/drivers/input/misc/wistron_btns.c @@ -273,6 +273,18 @@ static struct key_entry keymap_fs_amilo_pro_v2000[] = { { KE_END, 0 } }; +static struct key_entry keymap_fujitsu_n3510[] = { + { KE_KEY, 0x11, KEY_PROG1 }, + { KE_KEY, 0x12, KEY_PROG2 }, + { KE_KEY, 0x36, KEY_WWW }, + { KE_KEY, 0x31, KEY_MAIL }, + { KE_KEY, 0x71, KEY_STOPCD }, + { KE_KEY, 0x72, KEY_PLAYPAUSE }, + { KE_KEY, 0x74, KEY_REWIND }, + { KE_KEY, 0x78, KEY_FORWARD }, + { KE_END, 0 } +}; + static struct key_entry keymap_wistron_ms2141[] = { { KE_KEY, 0x11, KEY_PROG1 }, { KE_KEY, 0x12, KEY_PROG2 }, @@ -330,6 +342,15 @@ static struct dmi_system_id dmi_ids[] = { }, .driver_data = keymap_fs_amilo_pro_v2000 }, + { + .callback = dmi_matched, + .ident = "Fujitsu N3510", + .matches = { + DMI_MATCH(DMI_SYS_VENDOR, "FUJITSU"), + DMI_MATCH(DMI_PRODUCT_NAME, "N3510"), + }, + .driver_data = keymap_fujitsu_n3510 + }, { .callback = dmi_matched, .ident = "Acer Aspire 1500", -- cgit v1.2.3-18-g5258 From 86678dfddba55a7b9e2ea084d59be6500fec2256 Mon Sep 17 00:00:00 2001 From: Dave Airlie Date: Wed, 5 Apr 2006 18:10:11 +1000 Subject: [PATCH] drm: Fix issue reported by Coverity in drivers/char/drm/via_irq.c This patch tries to fix an issue reported in drivers/char/drm/via_irq.c by Coverity, please review and apply if correct. Error reported: CID: 3444 Checker: REVERSE_INULL (help) File: /export2/p4-coverity/mc2/linux26/drivers/char/drm/via_irq.c Function: via_driver_irq_wait Description: Pointer "dev_priv" dereferenced before NULL check Patch Description: Move de-referencing dev_priv to after the NULL check. Signed-off-by: Jayachandran C. Signed-off-by: Dave Airlie --- drivers/char/drm/via_irq.c | 5 +++-- 1 file changed, 3 insertions(+), 2 deletions(-) (limited to 'drivers') diff --git a/drivers/char/drm/via_irq.c b/drivers/char/drm/via_irq.c index 6152415644e..1228fa55355 100644 --- a/drivers/char/drm/via_irq.c +++ b/drivers/char/drm/via_irq.c @@ -198,7 +198,7 @@ via_driver_irq_wait(drm_device_t * dev, unsigned int irq, int force_sequence, unsigned int cur_irq_sequence; drm_via_irq_t *cur_irq = dev_priv->via_irqs; int ret = 0; - maskarray_t *masks = dev_priv->irq_masks; + maskarray_t *masks; int real_irq; DRM_DEBUG("%s\n", __FUNCTION__); @@ -221,7 +221,8 @@ via_driver_irq_wait(drm_device_t * dev, unsigned int irq, int force_sequence, __FUNCTION__, irq); return DRM_ERR(EINVAL); } - + + masks = dev_priv->irq_masks; cur_irq += real_irq; if (masks[real_irq][2] && !force_sequence) { -- cgit v1.2.3-18-g5258 From 195b3a2d57b81d30e3129575ef6c8a95b2c936b7 Mon Sep 17 00:00:00 2001 From: Dave Airlie Date: Wed, 5 Apr 2006 18:12:18 +1000 Subject: drm: drm_pci needs dma-mapping.h On alpha: WARNING: "dma_free_coherent" [drivers/char/drm/drm.ko] undefined! WARNING: "dma_alloc_coherent" [drivers/char/drm/drm.ko] undefined! Signed-off-by: Andrew Morton Signed-off-by: Dave Airlie --- drivers/char/drm/drm_pci.c | 1 + 1 file changed, 1 insertion(+) (limited to 'drivers') diff --git a/drivers/char/drm/drm_pci.c b/drivers/char/drm/drm_pci.c index b28ca9cea8a..86a0f1c2209 100644 --- a/drivers/char/drm/drm_pci.c +++ b/drivers/char/drm/drm_pci.c @@ -37,6 +37,7 @@ */ #include +#include #include "drmP.h" /**********************************************************************/ -- cgit v1.2.3-18-g5258 From 11bab7d2c86fe486e3581ac3dcdb349478ffb899 Mon Sep 17 00:00:00 2001 From: Dave Airlie Date: Wed, 5 Apr 2006 18:13:13 +1000 Subject: drm: remove master setting from add/remove context Clients can do this in the miniglx setups. Signed-off-by: Dave Airlie --- drivers/char/drm/drm_drv.c | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) (limited to 'drivers') diff --git a/drivers/char/drm/drm_drv.c b/drivers/char/drm/drm_drv.c index dc6bbe8a18d..3c0b882a8e7 100644 --- a/drivers/char/drm/drm_drv.c +++ b/drivers/char/drm/drm_drv.c @@ -75,8 +75,8 @@ static drm_ioctl_desc_t drm_ioctls[] = { [DRM_IOCTL_NR(DRM_IOCTL_SET_SAREA_CTX)] = {drm_setsareactx, DRM_AUTH|DRM_MASTER|DRM_ROOT_ONLY}, [DRM_IOCTL_NR(DRM_IOCTL_GET_SAREA_CTX)] = {drm_getsareactx, DRM_AUTH}, - [DRM_IOCTL_NR(DRM_IOCTL_ADD_CTX)] = {drm_addctx, DRM_AUTH|DRM_MASTER|DRM_ROOT_ONLY}, - [DRM_IOCTL_NR(DRM_IOCTL_RM_CTX)] = {drm_rmctx, DRM_AUTH|DRM_MASTER|DRM_ROOT_ONLY}, + [DRM_IOCTL_NR(DRM_IOCTL_ADD_CTX)] = {drm_addctx, DRM_AUTH|DRM_ROOT_ONLY}, + [DRM_IOCTL_NR(DRM_IOCTL_RM_CTX)] = {drm_rmctx, DRM_AUTH|DRM_ROOT_ONLY}, [DRM_IOCTL_NR(DRM_IOCTL_MOD_CTX)] = {drm_modctx, DRM_AUTH|DRM_MASTER|DRM_ROOT_ONLY}, [DRM_IOCTL_NR(DRM_IOCTL_GET_CTX)] = {drm_getctx, DRM_AUTH}, [DRM_IOCTL_NR(DRM_IOCTL_SWITCH_CTX)] = {drm_switchctx, DRM_AUTH|DRM_MASTER|DRM_ROOT_ONLY}, -- cgit v1.2.3-18-g5258 From 31f64bd101ea256f9fc4a7f1f1706d6417d5550a Mon Sep 17 00:00:00 2001 From: Dave Airlie Date: Fri, 7 Apr 2006 16:55:43 +1000 Subject: drm: deline a few large inlines in DRM code This patch moves a few large functions from drm_memory.h to drm_memory.c, with the following effect: text data bss dec hex filename 46305 1304 20 47629 ba0d new/drm.ko 46367 1304 20 47691 ba4b org/drm.ko 12969 1372 0 14341 3805 new/i810.ko 14712 1372 0 16084 3ed4 org/i810.ko 16447 1364 0 17811 4593 new/i830.ko 18198 1364 0 19562 4c6a org/i830.ko 11875 1324 0 13199 338f new/i915.ko 13025 1324 0 14349 380d org/i915.ko 23936 29288 0 53224 cfe8 new/mga.ko 27280 29288 0 56568 dcf8 org/mga.ko Please apply. Signed-off-by: Denis Vlasenko Signed-off-by: Dave Airlie --- drivers/char/drm/drm_memory.c | 117 ++++++++++++++++++++++++++++++++++++++++++ drivers/char/drm/drm_memory.h | 116 ++++------------------------------------- 2 files changed, 127 insertions(+), 106 deletions(-) (limited to 'drivers') diff --git a/drivers/char/drm/drm_memory.c b/drivers/char/drm/drm_memory.c index dddf8de6614..7ea00e3372f 100644 --- a/drivers/char/drm/drm_memory.c +++ b/drivers/char/drm/drm_memory.c @@ -80,6 +80,71 @@ void *drm_realloc(void *oldpt, size_t oldsize, size_t size, int area) } #if __OS_HAS_AGP +/* + * Find the drm_map that covers the range [offset, offset+size). + */ +drm_map_t *drm_lookup_map(unsigned long offset, + unsigned long size, drm_device_t * dev) +{ + struct list_head *list; + drm_map_list_t *r_list; + drm_map_t *map; + + list_for_each(list, &dev->maplist->head) { + r_list = (drm_map_list_t *) list; + map = r_list->map; + if (!map) + continue; + if (map->offset <= offset + && (offset + size) <= (map->offset + map->size)) + return map; + } + return NULL; +} + +void *agp_remap(unsigned long offset, unsigned long size, + drm_device_t * dev) +{ + unsigned long *phys_addr_map, i, num_pages = + PAGE_ALIGN(size) / PAGE_SIZE; + struct drm_agp_mem *agpmem; + struct page **page_map; + void *addr; + + size = PAGE_ALIGN(size); + +#ifdef __alpha__ + offset -= dev->hose->mem_space->start; +#endif + + for (agpmem = dev->agp->memory; agpmem; agpmem = agpmem->next) + if (agpmem->bound <= offset + && (agpmem->bound + (agpmem->pages << PAGE_SHIFT)) >= + (offset + size)) + break; + if (!agpmem) + return NULL; + + /* + * OK, we're mapping AGP space on a chipset/platform on which memory accesses by + * the CPU do not get remapped by the GART. We fix this by using the kernel's + * page-table instead (that's probably faster anyhow...). + */ + /* note: use vmalloc() because num_pages could be large... */ + page_map = vmalloc(num_pages * sizeof(struct page *)); + if (!page_map) + return NULL; + + phys_addr_map = + agpmem->memory->memory + (offset - agpmem->bound) / PAGE_SIZE; + for (i = 0; i < num_pages; ++i) + page_map[i] = pfn_to_page(phys_addr_map[i] >> PAGE_SHIFT); + addr = vmap(page_map, num_pages, VM_IOREMAP, PAGE_AGP); + vfree(page_map); + + return addr; +} + /** Wrapper around agp_allocate_memory() */ DRM_AGP_MEM *drm_alloc_agp(drm_device_t * dev, int pages, u32 type) { @@ -104,4 +169,56 @@ int drm_unbind_agp(DRM_AGP_MEM * handle) return drm_agp_unbind_memory(handle); } #endif /* agp */ + +void *drm_ioremap(unsigned long offset, unsigned long size, + drm_device_t * dev) +{ + if (drm_core_has_AGP(dev) && dev->agp && dev->agp->cant_use_aperture) { + drm_map_t *map = drm_lookup_map(offset, size, dev); + + if (map && map->type == _DRM_AGP) + return agp_remap(offset, size, dev); + } + return ioremap(offset, size); +} +EXPORT_SYMBOL(drm_ioremap); + +void *drm_ioremap_nocache(unsigned long offset, + unsigned long size, drm_device_t * dev) +{ + if (drm_core_has_AGP(dev) && dev->agp && dev->agp->cant_use_aperture) { + drm_map_t *map = drm_lookup_map(offset, size, dev); + + if (map && map->type == _DRM_AGP) + return agp_remap(offset, size, dev); + } + return ioremap_nocache(offset, size); +} + +void drm_ioremapfree(void *pt, unsigned long size, + drm_device_t * dev) +{ + /* + * This is a bit ugly. It would be much cleaner if the DRM API would use separate + * routines for handling mappings in the AGP space. Hopefully this can be done in + * a future revision of the interface... + */ + if (drm_core_has_AGP(dev) && dev->agp && dev->agp->cant_use_aperture + && ((unsigned long)pt >= VMALLOC_START + && (unsigned long)pt < VMALLOC_END)) { + unsigned long offset; + drm_map_t *map; + + offset = drm_follow_page(pt) | ((unsigned long)pt & ~PAGE_MASK); + map = drm_lookup_map(offset, size, dev); + if (map && map->type == _DRM_AGP) { + vunmap(pt); + return; + } + } + + iounmap(pt); +} +EXPORT_SYMBOL(drm_ioremapfree); + #endif /* debug_memory */ diff --git a/drivers/char/drm/drm_memory.h b/drivers/char/drm/drm_memory.h index 3732a61c376..645a08878e5 100644 --- a/drivers/char/drm/drm_memory.h +++ b/drivers/char/drm/drm_memory.h @@ -60,67 +60,11 @@ /* * Find the drm_map that covers the range [offset, offset+size). */ -static inline drm_map_t *drm_lookup_map(unsigned long offset, - unsigned long size, drm_device_t * dev) -{ - struct list_head *list; - drm_map_list_t *r_list; - drm_map_t *map; - - list_for_each(list, &dev->maplist->head) { - r_list = (drm_map_list_t *) list; - map = r_list->map; - if (!map) - continue; - if (map->offset <= offset - && (offset + size) <= (map->offset + map->size)) - return map; - } - return NULL; -} - -static inline void *agp_remap(unsigned long offset, unsigned long size, - drm_device_t * dev) -{ - unsigned long *phys_addr_map, i, num_pages = - PAGE_ALIGN(size) / PAGE_SIZE; - struct drm_agp_mem *agpmem; - struct page **page_map; - void *addr; - - size = PAGE_ALIGN(size); - -#ifdef __alpha__ - offset -= dev->hose->mem_space->start; -#endif +drm_map_t *drm_lookup_map(unsigned long offset, + unsigned long size, drm_device_t * dev); - for (agpmem = dev->agp->memory; agpmem; agpmem = agpmem->next) - if (agpmem->bound <= offset - && (agpmem->bound + (agpmem->pages << PAGE_SHIFT)) >= - (offset + size)) - break; - if (!agpmem) - return NULL; - - /* - * OK, we're mapping AGP space on a chipset/platform on which memory accesses by - * the CPU do not get remapped by the GART. We fix this by using the kernel's - * page-table instead (that's probably faster anyhow...). - */ - /* note: use vmalloc() because num_pages could be large... */ - page_map = vmalloc(num_pages * sizeof(struct page *)); - if (!page_map) - return NULL; - - phys_addr_map = - agpmem->memory->memory + (offset - agpmem->bound) / PAGE_SIZE; - for (i = 0; i < num_pages; ++i) - page_map[i] = pfn_to_page(phys_addr_map[i] >> PAGE_SHIFT); - addr = vmap(page_map, num_pages, VM_IOREMAP, PAGE_AGP); - vfree(page_map); - - return addr; -} +void *agp_remap(unsigned long offset, unsigned long size, + drm_device_t * dev); static inline unsigned long drm_follow_page(void *vaddr) { @@ -152,51 +96,11 @@ static inline unsigned long drm_follow_page(void *vaddr) #endif -static inline void *drm_ioremap(unsigned long offset, unsigned long size, - drm_device_t * dev) -{ - if (drm_core_has_AGP(dev) && dev->agp && dev->agp->cant_use_aperture) { - drm_map_t *map = drm_lookup_map(offset, size, dev); +void *drm_ioremap(unsigned long offset, unsigned long size, + drm_device_t * dev); - if (map && map->type == _DRM_AGP) - return agp_remap(offset, size, dev); - } - return ioremap(offset, size); -} +void *drm_ioremap_nocache(unsigned long offset, + unsigned long size, drm_device_t * dev); -static inline void *drm_ioremap_nocache(unsigned long offset, - unsigned long size, drm_device_t * dev) -{ - if (drm_core_has_AGP(dev) && dev->agp && dev->agp->cant_use_aperture) { - drm_map_t *map = drm_lookup_map(offset, size, dev); - - if (map && map->type == _DRM_AGP) - return agp_remap(offset, size, dev); - } - return ioremap_nocache(offset, size); -} - -static inline void drm_ioremapfree(void *pt, unsigned long size, - drm_device_t * dev) -{ - /* - * This is a bit ugly. It would be much cleaner if the DRM API would use separate - * routines for handling mappings in the AGP space. Hopefully this can be done in - * a future revision of the interface... - */ - if (drm_core_has_AGP(dev) && dev->agp && dev->agp->cant_use_aperture - && ((unsigned long)pt >= VMALLOC_START - && (unsigned long)pt < VMALLOC_END)) { - unsigned long offset; - drm_map_t *map; - - offset = drm_follow_page(pt) | ((unsigned long)pt & ~PAGE_MASK); - map = drm_lookup_map(offset, size, dev); - if (map && map->type == _DRM_AGP) { - vunmap(pt); - return; - } - } - - iounmap(pt); -} +void drm_ioremapfree(void *pt, unsigned long size, + drm_device_t * dev); -- cgit v1.2.3-18-g5258 From 438f2a7401ec5d8f85923a7c3e6da444f097a3a1 Mon Sep 17 00:00:00 2001 From: Imre Deak Date: Tue, 11 Apr 2006 23:41:32 -0400 Subject: Input: ads7846 - add pen_down sysfs attribute It's handy for userspace diagnostics to see the pen down status, to see whether the touchscreen is "stuck" (shortcircuited). Signed-off-by: Imre Deak Signed-off-by: Juha Yrjola Signed-off-by: David Brownell Signed-off-by: Dmitry Torokhov --- drivers/input/touchscreen/ads7846.c | 19 +++++++++++++++++++ 1 file changed, 19 insertions(+) (limited to 'drivers') diff --git a/drivers/input/touchscreen/ads7846.c b/drivers/input/touchscreen/ads7846.c index 46d1fec2cfd..7f384a694d8 100644 --- a/drivers/input/touchscreen/ads7846.c +++ b/drivers/input/touchscreen/ads7846.c @@ -233,6 +233,21 @@ SHOW(temp1) SHOW(vaux) SHOW(vbatt) +static int is_pen_down(struct device *dev) +{ + struct ads7846 *ts = dev_get_drvdata(dev); + + return ts->pendown; +} + +static ssize_t ads7846_pen_down_show(struct device *dev, + struct device_attribute *attr, char *buf) +{ + return sprintf(buf, "%u\n", is_pen_down(dev)); +} + +static DEVICE_ATTR(pen_down, S_IRUGO, ads7846_pen_down_show, NULL); + /*--------------------------------------------------------------------------*/ /* @@ -559,6 +574,8 @@ static int __devinit ads7846_probe(struct spi_device *spi) device_create_file(&spi->dev, &dev_attr_vbatt); device_create_file(&spi->dev, &dev_attr_vaux); + device_create_file(&spi->dev, &dev_attr_pen_down); + err = input_register_device(input_dev); if (err) goto err_free_irq; @@ -582,6 +599,8 @@ static int __devexit ads7846_remove(struct spi_device *spi) if (ts->irq_disabled) enable_irq(ts->spi->irq); + device_remove_file(&spi->dev, &dev_attr_pen_down); + if (ts->model == 7846) { device_remove_file(&spi->dev, &dev_attr_temp0); device_remove_file(&spi->dev, &dev_attr_temp1); -- cgit v1.2.3-18-g5258 From 53a0ef89e95c725f3faab98573770aeb7429c1a3 Mon Sep 17 00:00:00 2001 From: Imre Deak Date: Tue, 11 Apr 2006 23:41:49 -0400 Subject: Input: ads7846 - power down ADC a bit later Submit a seperate request for powering down the ADC in ads7846, doing it after the last read request. Otherwise some of the read values are incorrect. Signed-off-by: Imre Deak Signed-off-by: Juha Yrjola Signed-off-by: David Brownell Signed-off-by: Dmitry Torokhov --- drivers/input/touchscreen/ads7846.c | 21 ++++++++++++++++++--- 1 file changed, 18 insertions(+), 3 deletions(-) (limited to 'drivers') diff --git a/drivers/input/touchscreen/ads7846.c b/drivers/input/touchscreen/ads7846.c index 7f384a694d8..54d43347786 100644 --- a/drivers/input/touchscreen/ads7846.c +++ b/drivers/input/touchscreen/ads7846.c @@ -72,10 +72,11 @@ struct ads7846 { u16 vref_delay_usecs; u16 x_plate_ohms; - u8 read_x, read_y, read_z1, read_z2; + u8 read_x, read_y, read_z1, read_z2, pwrdown; + u16 dummy; /* for the pwrdown read */ struct ts_event tc; - struct spi_transfer xfer[8]; + struct spi_transfer xfer[10]; struct spi_message msg; spinlock_t lock; @@ -125,7 +126,9 @@ struct ads7846 { #define READ_Y (READ_12BIT_DFR(y) | ADS_PD10_ADC_ON) #define READ_Z1 (READ_12BIT_DFR(z1) | ADS_PD10_ADC_ON) #define READ_Z2 (READ_12BIT_DFR(z2) | ADS_PD10_ADC_ON) -#define READ_X (READ_12BIT_DFR(x) | ADS_PD10_PDOWN) /* LAST */ + +#define READ_X (READ_12BIT_DFR(x) | ADS_PD10_ADC_ON) +#define PWRDOWN (READ_12BIT_DFR(y) | ADS_PD10_PDOWN) /* LAST */ /* single-ended samples need to first power up reference voltage; * we leave both ADC and VREF powered @@ -541,6 +544,18 @@ static int __devinit ads7846_probe(struct spi_device *spi) x++; x->rx_buf = &ts->tc.x; x->len = 2; + spi_message_add_tail(x, &ts->msg); + + /* power down */ + x++; + ts->pwrdown = PWRDOWN; + x->tx_buf = &ts->pwrdown; + x->len = 1; + spi_message_add_tail(x, &ts->msg); + + x++; + x->rx_buf = &ts->dummy; + x->len = 2; CS_CHANGE(*x); spi_message_add_tail(x, &ts->msg); -- cgit v1.2.3-18-g5258 From 0b7018aae7e1798f55f736b9a77c201708aa0e33 Mon Sep 17 00:00:00 2001 From: Imre Deak Date: Tue, 11 Apr 2006 23:42:03 -0400 Subject: Input: ads7846 - debouncing and rudimentary sample filtering MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Some touchscreens seem to oscillate heavily for a while after touching the screen.  Implement support for sampling the screen until we get two consecutive values that are close enough. Signed-off-by: Imre Deak Signed-off-by: Juha Yrjola Signed-off-by: David Brownell Signed-off-by: Dmitry Torokhov --- drivers/input/touchscreen/ads7846.c | 156 +++++++++++++++++++++++++++--------- 1 file changed, 118 insertions(+), 38 deletions(-) (limited to 'drivers') diff --git a/drivers/input/touchscreen/ads7846.c b/drivers/input/touchscreen/ads7846.c index 54d43347786..8670cd13bd5 100644 --- a/drivers/input/touchscreen/ads7846.c +++ b/drivers/input/touchscreen/ads7846.c @@ -77,7 +77,13 @@ struct ads7846 { struct ts_event tc; struct spi_transfer xfer[10]; - struct spi_message msg; + struct spi_message msg[5]; + int msg_idx; + int read_cnt; + int last_read; + + u16 debounce_max; + u16 debounce_tol; spinlock_t lock; struct timer_list timer; /* P: lock */ @@ -167,7 +173,7 @@ static int ads7846_read12_ser(struct device *dev, unsigned command) if (!req) return -ENOMEM; - INIT_LIST_HEAD(&req->msg.transfers); + spi_message_init(&req->msg); /* activate reference, so it has time to settle; */ req->ref_on = REF_ON; @@ -344,31 +350,76 @@ static void ads7846_rx(void *ads) spin_unlock_irqrestore(&ts->lock, flags); } +static void ads7846_debounce(void *ads) +{ + struct ads7846 *ts = ads; + struct spi_message *m; + struct spi_transfer *t; + u16 val; + int status; + + m = &ts->msg[ts->msg_idx]; + t = list_entry(m->transfers.prev, struct spi_transfer, transfer_list); + val = (*(u16 *)t->rx_buf) >> 3; + + if (!ts->read_cnt || (abs(ts->last_read - val) > ts->debounce_tol + && ts->read_cnt < ts->debounce_max)) { + /* Repeat it, if this was the first read or the read wasn't + * consistent enough + */ + ts->read_cnt++; + ts->last_read = val; + } else { + /* Go for the next read */ + ts->msg_idx++; + ts->read_cnt = 0; + m++; + } + status = spi_async(ts->spi, m); + if (status) + dev_err(&ts->spi->dev, "spi_async --> %d\n", + status); +} + static void ads7846_timer(unsigned long handle) { struct ads7846 *ts = (void *)handle; int status = 0; - unsigned long flags; + + ts->msg_idx = 0; + status = spi_async(ts->spi, &ts->msg[0]); + if (status) + dev_err(&ts->spi->dev, "spi_async --> %d\n", status); +} + +static irqreturn_t ads7846_irq(int irq, void *handle, struct pt_regs *regs) +{ + struct ads7846 *ts = handle; + unsigned long flags; + int r = IRQ_HANDLED; spin_lock_irqsave(&ts->lock, flags); - if (!ts->pending) { - ts->pending = 1; + if (ts->irq_disabled) + r = IRQ_HANDLED; + else { if (!ts->irq_disabled) { + /* REVISIT irq logic for many ARM chips has cloned a + * bug wherein disabling an irq in its handler won't + * work;(it's disabled lazily, and too late to work. + * until all their irq logic is fixed, we must shadow + * that state here. + */ ts->irq_disabled = 1; + disable_irq(ts->spi->irq); } - status = spi_async(ts->spi, &ts->msg); - if (status) - dev_err(&ts->spi->dev, "spi_async --> %d\n", - status); + if (!ts->pending) { + ts->pending = 1; + mod_timer(&ts->timer, jiffies); + } } spin_unlock_irqrestore(&ts->lock, flags); -} - -static irqreturn_t ads7846_irq(int irq, void *handle, struct pt_regs *regs) -{ - ads7846_timer((unsigned long) handle); - return IRQ_HANDLED; + return r; } /*--------------------------------------------------------------------------*/ @@ -426,6 +477,7 @@ static int __devinit ads7846_probe(struct spi_device *spi) struct ads7846 *ts; struct input_dev *input_dev; struct ads7846_platform_data *pdata = spi->dev.platform_data; + struct spi_message *m; struct spi_transfer *x; int err; @@ -472,6 +524,8 @@ static int __devinit ads7846_probe(struct spi_device *spi) ts->model = pdata->model ? : 7846; ts->vref_delay_usecs = pdata->vref_delay_usecs ? : 100; ts->x_plate_ohms = pdata->x_plate_ohms ? : 400; + ts->debounce_max = pdata->debounce_max ? : 1; + ts->debounce_tol = pdata->debounce_tol ? : 10; snprintf(ts->phys, sizeof(ts->phys), "%s/input0", spi->dev.bus_id); @@ -495,72 +549,98 @@ static int __devinit ads7846_probe(struct spi_device *spi) /* set up the transfers to read touchscreen state; this assumes we * use formula #2 for pressure, not #3. */ - INIT_LIST_HEAD(&ts->msg.transfers); + m = &ts->msg[0]; x = ts->xfer; + spi_message_init(m); + /* y- still on; turn on only y+ (and ADC) */ ts->read_y = READ_Y; x->tx_buf = &ts->read_y; x->len = 1; - spi_message_add_tail(x, &ts->msg); + spi_message_add_tail(x, m); x++; x->rx_buf = &ts->tc.y; x->len = 2; - spi_message_add_tail(x, &ts->msg); + spi_message_add_tail(x, m); + + m->complete = ads7846_debounce; + m->context = ts; + + m++; + spi_message_init(m); + + /* turn y- off, x+ on, then leave in lowpower */ + x++; + ts->read_x = READ_X; + x->tx_buf = &ts->read_x; + x->len = 1; + spi_message_add_tail(x, m); + + x++; + x->rx_buf = &ts->tc.x; + x->len = 2; + spi_message_add_tail(x, m); + + m->complete = ads7846_debounce; + m->context = ts; /* turn y+ off, x- on; we'll use formula #2 */ if (ts->model == 7846) { + m++; + spi_message_init(m); + x++; ts->read_z1 = READ_Z1; x->tx_buf = &ts->read_z1; x->len = 1; - spi_message_add_tail(x, &ts->msg); + spi_message_add_tail(x, m); x++; x->rx_buf = &ts->tc.z1; x->len = 2; - spi_message_add_tail(x, &ts->msg); + spi_message_add_tail(x, m); + + m->complete = ads7846_debounce; + m->context = ts; + + m++; + spi_message_init(m); x++; ts->read_z2 = READ_Z2; x->tx_buf = &ts->read_z2; x->len = 1; - spi_message_add_tail(x, &ts->msg); + spi_message_add_tail(x, m); x++; x->rx_buf = &ts->tc.z2; x->len = 2; - spi_message_add_tail(x, &ts->msg); - } + spi_message_add_tail(x, m); - /* turn y- off, x+ on, then leave in lowpower */ - x++; - ts->read_x = READ_X; - x->tx_buf = &ts->read_x; - x->len = 1; - spi_message_add_tail(x, &ts->msg); - - x++; - x->rx_buf = &ts->tc.x; - x->len = 2; - spi_message_add_tail(x, &ts->msg); + m->complete = ads7846_debounce; + m->context = ts; + } /* power down */ + m++; + spi_message_init(m); + x++; ts->pwrdown = PWRDOWN; x->tx_buf = &ts->pwrdown; x->len = 1; - spi_message_add_tail(x, &ts->msg); + spi_message_add_tail(x, m); x++; x->rx_buf = &ts->dummy; x->len = 2; CS_CHANGE(*x); - spi_message_add_tail(x, &ts->msg); + spi_message_add_tail(x, m); - ts->msg.complete = ads7846_rx; - ts->msg.context = ts; + m->complete = ads7846_rx; + m->context = ts; if (request_irq(spi->irq, ads7846_irq, SA_SAMPLE_RANDOM | SA_TRIGGER_FALLING, -- cgit v1.2.3-18-g5258 From c4febb94dae915da4423b81c487eabed9cef5cba Mon Sep 17 00:00:00 2001 From: Juha Yrjola Date: Tue, 11 Apr 2006 23:42:25 -0400 Subject: Input: ads7846 - use msleep() instead of udelay() in suspend Sometimes a polling loop had a hard time changing state without pre-emption enabled. Use msleep instead, it's better anyway. Signed-off-by: Juha Yrjola Signed-off-by: David Brownell Signed-off-by: Dmitry Torokhov --- drivers/input/touchscreen/ads7846.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'drivers') diff --git a/drivers/input/touchscreen/ads7846.c b/drivers/input/touchscreen/ads7846.c index 8670cd13bd5..bdec112e89c 100644 --- a/drivers/input/touchscreen/ads7846.c +++ b/drivers/input/touchscreen/ads7846.c @@ -449,7 +449,7 @@ ads7846_suspend(struct spi_device *spi, pm_message_t message) while (ts->pendown || ts->pending) { spin_unlock_irqrestore(&ts->lock, flags); - udelay(10); + msleep(1); spin_lock_irqsave(&ts->lock, flags); } } -- cgit v1.2.3-18-g5258 From 7de90a8cb9c51145d7f60d8db17ce0fa07d1b281 Mon Sep 17 00:00:00 2001 From: Imre Deak Date: Tue, 11 Apr 2006 23:43:55 -0400 Subject: Input: ads7846 - miscellaneous fixes - Add disable attribute to support device locking mode where unintentional touch event shouldn't wake up the system; - Update comments; - Add missing spin_lock_init; - Do device resume with the lock held; - Do cleanup calls / free memory in the reverse order of initialization. Signed-off-by: Imre Deak Signed-off-by: David Brownell Signed-off-by: Dmitry Torokhov --- drivers/input/touchscreen/ads7846.c | 144 ++++++++++++++++++++++++++++-------- 1 file changed, 114 insertions(+), 30 deletions(-) (limited to 'drivers') diff --git a/drivers/input/touchscreen/ads7846.c b/drivers/input/touchscreen/ads7846.c index bdec112e89c..fec3b9b2230 100644 --- a/drivers/input/touchscreen/ads7846.c +++ b/drivers/input/touchscreen/ads7846.c @@ -2,6 +2,8 @@ * ADS7846 based touchscreen and sensor driver * * Copyright (c) 2005 David Brownell + * Copyright (c) 2006 Nokia Corporation + * Various changes: Imre Deak * * Using code from: * - corgi_ts.c @@ -34,17 +36,25 @@ /* - * This code has been lightly tested on an ads7846. + * This code has been tested on an ads7846 / N770 device. * Support for ads7843 and ads7845 has only been stubbed in. * - * Not yet done: investigate the values reported. Are x/y/pressure - * event values sane enough for X11? How accurate are the temperature - * and voltage readings? (System-specific calibration should support + * Not yet done: How accurate are the temperature and voltage + * readings? (System-specific calibration should support * accuracy of 0.3 degrees C; otherwise it's 2.0 degrees.) * + * IRQ handling needs a workaround because of a shortcoming in handling + * edge triggered IRQs on some platforms like the OMAP1/2. These + * platforms don't handle the ARM lazy IRQ disabling properly, thus we + * have to maintain our own SW IRQ disabled status. This should be + * removed as soon as the affected platform's IRQ handling is fixed. + * * app note sbaa036 talks in more detail about accurate sampling... * that ought to help in situations like LCDs inducing noise (which * can also be helped by using synch signals) and more generally. + * This driver tries to utilize the measures described in the app + * note. The strength of filtering can be set in the board-* specific + * files. */ #define TS_POLL_PERIOD msecs_to_jiffies(10) @@ -91,6 +101,7 @@ struct ads7846 { unsigned pending:1; /* P: lock */ // FIXME remove "irq_disabled" unsigned irq_disabled:1; /* P: lock */ + unsigned disabled:1; }; /* leave chip selected when we're done, for quicker re-select? */ @@ -161,6 +172,9 @@ struct ser_req { struct spi_transfer xfer[6]; }; +static void ads7846_enable(struct ads7846 *ts); +static void ads7846_disable(struct ads7846 *ts); + static int ads7846_read12_ser(struct device *dev, unsigned command) { struct spi_device *spi = to_spi_device(dev); @@ -257,6 +271,37 @@ static ssize_t ads7846_pen_down_show(struct device *dev, static DEVICE_ATTR(pen_down, S_IRUGO, ads7846_pen_down_show, NULL); +static ssize_t ads7846_disable_show(struct device *dev, + struct device_attribute *attr, char *buf) +{ + struct ads7846 *ts = dev_get_drvdata(dev); + + return sprintf(buf, "%u\n", ts->disabled); +} + +static ssize_t ads7846_disable_store(struct device *dev, + struct device_attribute *attr, + const char *buf, size_t count) +{ + struct ads7846 *ts = dev_get_drvdata(dev); + char *endp; + int i; + + i = simple_strtoul(buf, &endp, 10); + spin_lock_irq(&ts->lock); + + if (i) + ads7846_disable(ts); + else + ads7846_enable(ts); + + spin_unlock_irq(&ts->lock); + + return count; +} + +static DEVICE_ATTR(disable, 0664, ads7846_disable_show, ads7846_disable_store); + /*--------------------------------------------------------------------------*/ /* @@ -396,12 +441,9 @@ static irqreturn_t ads7846_irq(int irq, void *handle, struct pt_regs *regs) { struct ads7846 *ts = handle; unsigned long flags; - int r = IRQ_HANDLED; spin_lock_irqsave(&ts->lock, flags); - if (ts->irq_disabled) - r = IRQ_HANDLED; - else { + if (likely(!ts->irq_disabled && !ts->disabled)) { if (!ts->irq_disabled) { /* REVISIT irq logic for many ARM chips has cloned a * bug wherein disabling an irq in its handler won't @@ -419,20 +461,17 @@ static irqreturn_t ads7846_irq(int irq, void *handle, struct pt_regs *regs) } } spin_unlock_irqrestore(&ts->lock, flags); - return r; + + return IRQ_HANDLED; } /*--------------------------------------------------------------------------*/ -static int -ads7846_suspend(struct spi_device *spi, pm_message_t message) +/* Must be called with ts->lock held */ +static void ads7846_disable(struct ads7846 *ts) { - struct ads7846 *ts = dev_get_drvdata(&spi->dev); - unsigned long flags; - - spin_lock_irqsave(&ts->lock, flags); - - spi->dev.power.power_state = message; + if (ts->disabled) + return; /* are we waiting for IRQ, or polling? */ if (!ts->pendown) { @@ -448,9 +487,9 @@ ads7846_suspend(struct spi_device *spi, pm_message_t message) mod_timer(&ts->timer, jiffies); while (ts->pendown || ts->pending) { - spin_unlock_irqrestore(&ts->lock, flags); + spin_unlock_irq(&ts->lock); msleep(1); - spin_lock_irqsave(&ts->lock, flags); + spin_lock_irq(&ts->lock); } } @@ -458,17 +497,46 @@ ads7846_suspend(struct spi_device *spi, pm_message_t message) * leave it that way after every request */ - spin_unlock_irqrestore(&ts->lock, flags); + ts->disabled = 1; +} + +/* Must be called with ts->lock held */ +static void ads7846_enable(struct ads7846 *ts) +{ + if (!ts->disabled) + return; + + ts->disabled = 0; + ts->irq_disabled = 0; + enable_irq(ts->spi->irq); +} + +static int ads7846_suspend(struct spi_device *spi, pm_message_t message) +{ + struct ads7846 *ts = dev_get_drvdata(&spi->dev); + + spin_lock_irq(&ts->lock); + + spi->dev.power.power_state = message; + ads7846_disable(ts); + + spin_unlock_irq(&ts->lock); + return 0; + } static int ads7846_resume(struct spi_device *spi) { struct ads7846 *ts = dev_get_drvdata(&spi->dev); - ts->irq_disabled = 0; - enable_irq(ts->spi->irq); + spin_lock_irq(&ts->lock); + spi->dev.power.power_state = PMSG_ON; + ads7846_enable(ts); + + spin_unlock_irq(&ts->lock); + return 0; } @@ -521,6 +589,8 @@ static int __devinit ads7846_probe(struct spi_device *spi) ts->timer.data = (unsigned long) ts; ts->timer.function = ads7846_timer; + spin_lock_init(&ts->lock); + ts->model = pdata->model ? : 7846; ts->vref_delay_usecs = pdata->vref_delay_usecs ? : 100; ts->x_plate_ohms = pdata->x_plate_ohms ? : 400; @@ -671,13 +741,25 @@ static int __devinit ads7846_probe(struct spi_device *spi) device_create_file(&spi->dev, &dev_attr_pen_down); + device_create_file(&spi->dev, &dev_attr_disable); + err = input_register_device(input_dev); if (err) - goto err_free_irq; + goto err_remove_attr; return 0; - err_free_irq: + err_remove_attr: + device_remove_file(&spi->dev, &dev_attr_disable); + device_remove_file(&spi->dev, &dev_attr_pen_down); + if (ts->model == 7846) { + device_remove_file(&spi->dev, &dev_attr_temp1); + device_remove_file(&spi->dev, &dev_attr_temp0); + } + if (ts->model != 7845) + device_remove_file(&spi->dev, &dev_attr_vbatt); + device_remove_file(&spi->dev, &dev_attr_vaux); + free_irq(spi->irq, ts); err_free_mem: input_free_device(input_dev); @@ -689,22 +771,24 @@ static int __devexit ads7846_remove(struct spi_device *spi) { struct ads7846 *ts = dev_get_drvdata(&spi->dev); + input_unregister_device(ts->input); + ads7846_suspend(spi, PMSG_SUSPEND); - free_irq(ts->spi->irq, ts); - if (ts->irq_disabled) - enable_irq(ts->spi->irq); + device_remove_file(&spi->dev, &dev_attr_disable); device_remove_file(&spi->dev, &dev_attr_pen_down); - if (ts->model == 7846) { - device_remove_file(&spi->dev, &dev_attr_temp0); device_remove_file(&spi->dev, &dev_attr_temp1); + device_remove_file(&spi->dev, &dev_attr_temp0); } if (ts->model != 7845) device_remove_file(&spi->dev, &dev_attr_vbatt); device_remove_file(&spi->dev, &dev_attr_vaux); - input_unregister_device(ts->input); + free_irq(ts->spi->irq, ts); + if (ts->irq_disabled) + enable_irq(ts->spi->irq); + kfree(ts); dev_dbg(&spi->dev, "unregistered touchscreen\n"); -- cgit v1.2.3-18-g5258 From c9e617a563ad646239270fa2222cdb06966cf1fa Mon Sep 17 00:00:00 2001 From: Imre Deak Date: Tue, 11 Apr 2006 23:44:05 -0400 Subject: Input: ads7846 - handle IRQs that were latched during disabled IRQs The pen down IRQ will toggle during each X,Y,Z measurement cycle. Even though the IRQ is disabled it will be latched and delivered when after enable_irq. Thus in the IRQ handler we must avoid starting a new measurement cycle when such an "unwanted" IRQ happens. Add a get_pendown_state platform function, which will probably determine this by reading the current GPIO level of the pen IRQ pin. Move the IRQ reenabling from the SPI RX function to the timer. After the last power down message the pen IRQ pin is still active for a while and get_pendown_state would report incorrectly a pen down state. When suspending we should check the ts->pending flag instead of ts->pendown, since the timer can be pending regardless of ts->pendown. Also if ts->pending is set we can be sure that the timer is running, so no need to rearm it. Similarly if ts->pending is not set we can be sure that the IRQ is enabled (and the timer is not). Signed-off-by: Imre Deak Signed-off-by: David Brownell Signed-off-by: Dmitry Torokhov --- drivers/input/touchscreen/ads7846.c | 82 ++++++++++++++++++++++--------------- 1 file changed, 48 insertions(+), 34 deletions(-) (limited to 'drivers') diff --git a/drivers/input/touchscreen/ads7846.c b/drivers/input/touchscreen/ads7846.c index fec3b9b2230..e7cabf12c8d 100644 --- a/drivers/input/touchscreen/ads7846.c +++ b/drivers/input/touchscreen/ads7846.c @@ -102,6 +102,8 @@ struct ads7846 { // FIXME remove "irq_disabled" unsigned irq_disabled:1; /* P: lock */ unsigned disabled:1; + + int (*get_pendown_state)(void); }; /* leave chip selected when we're done, for quicker re-select? */ @@ -175,6 +177,12 @@ struct ser_req { static void ads7846_enable(struct ads7846 *ts); static void ads7846_disable(struct ads7846 *ts); +static int device_suspended(struct device *dev) +{ + struct ads7846 *ts = dev_get_drvdata(dev); + return dev->power.power_state.event != PM_EVENT_ON || ts->disabled; +} + static int ads7846_read12_ser(struct device *dev, unsigned command) { struct spi_device *spi = to_spi_device(dev); @@ -227,8 +235,10 @@ static int ads7846_read12_ser(struct device *dev, unsigned command) for (i = 0; i < 6; i++) spi_message_add_tail(&req->xfer[i], &req->msg); + ts->irq_disabled = 1; disable_irq(spi->irq); status = spi_sync(spi, &req->msg); + ts->irq_disabled = 0; enable_irq(spi->irq); if (req->msg.status) @@ -333,7 +343,7 @@ static void ads7846_rx(void *ads) if (x == MAX_12BIT) x = 0; - if (x && z1 && ts->spi->dev.power.power_state.event == PM_EVENT_ON) { + if (likely(x && z1 && !device_suspended(&ts->spi->dev))) { /* compute touch pressure resistance using equation #2 */ Rt = z2; Rt -= z1; @@ -377,20 +387,10 @@ static void ads7846_rx(void *ads) x, y, Rt, Rt ? "" : " UP"); #endif - /* don't retrigger while we're suspended */ spin_lock_irqsave(&ts->lock, flags); ts->pendown = (Rt != 0); - ts->pending = 0; - - if (ts->spi->dev.power.power_state.event == PM_EVENT_ON) { - if (ts->pendown) - mod_timer(&ts->timer, jiffies + TS_POLL_PERIOD); - else if (ts->irq_disabled) { - ts->irq_disabled = 0; - enable_irq(ts->spi->irq); - } - } + mod_timer(&ts->timer, jiffies + TS_POLL_PERIOD); spin_unlock_irqrestore(&ts->lock, flags); } @@ -431,10 +431,25 @@ static void ads7846_timer(unsigned long handle) struct ads7846 *ts = (void *)handle; int status = 0; - ts->msg_idx = 0; - status = spi_async(ts->spi, &ts->msg[0]); - if (status) - dev_err(&ts->spi->dev, "spi_async --> %d\n", status); + spin_lock_irq(&ts->lock); + + if (unlikely(ts->msg_idx && !ts->pendown)) { + /* measurment cycle ended */ + if (!device_suspended(&ts->spi->dev)) { + ts->irq_disabled = 0; + enable_irq(ts->spi->irq); + } + ts->pending = 0; + ts->msg_idx = 0; + } else { + /* pen is still down, continue with the measurement */ + ts->msg_idx = 0; + status = spi_async(ts->spi, &ts->msg[0]); + if (status) + dev_err(&ts->spi->dev, "spi_async --> %d\n", status); + } + + spin_unlock_irq(&ts->lock); } static irqreturn_t ads7846_irq(int irq, void *handle, struct pt_regs *regs) @@ -443,7 +458,7 @@ static irqreturn_t ads7846_irq(int irq, void *handle, struct pt_regs *regs) unsigned long flags; spin_lock_irqsave(&ts->lock, flags); - if (likely(!ts->irq_disabled && !ts->disabled)) { + if (likely(ts->get_pendown_state())) { if (!ts->irq_disabled) { /* REVISIT irq logic for many ARM chips has cloned a * bug wherein disabling an irq in its handler won't @@ -452,10 +467,7 @@ static irqreturn_t ads7846_irq(int irq, void *handle, struct pt_regs *regs) * that state here. */ ts->irq_disabled = 1; - disable_irq(ts->spi->irq); - } - if (!ts->pending) { ts->pending = 1; mod_timer(&ts->timer, jiffies); } @@ -473,20 +485,17 @@ static void ads7846_disable(struct ads7846 *ts) if (ts->disabled) return; + ts->disabled = 1; + /* are we waiting for IRQ, or polling? */ - if (!ts->pendown) { - if (!ts->irq_disabled) { - ts->irq_disabled = 1; - disable_irq(ts->spi->irq); - } + if (!ts->pending) { + ts->irq_disabled = 1; + disable_irq(ts->spi->irq); } else { - /* polling; force a final SPI completion; - * that will clean things up neatly + /* the timer will run at least once more, and + * leave everything in a clean state, IRQ disabled */ - if (!ts->pending) - mod_timer(&ts->timer, jiffies); - - while (ts->pendown || ts->pending) { + while (ts->pending) { spin_unlock_irq(&ts->lock); msleep(1); spin_lock_irq(&ts->lock); @@ -497,7 +506,6 @@ static void ads7846_disable(struct ads7846 *ts) * leave it that way after every request */ - ts->disabled = 1; } /* Must be called with ts->lock held */ @@ -566,6 +574,11 @@ static int __devinit ads7846_probe(struct spi_device *spi) return -EINVAL; } + if (pdata->get_pendown_state == NULL) { + dev_dbg(&spi->dev, "no get_pendown_state function?\n"); + return -EINVAL; + } + /* We'd set the wordsize to 12 bits ... except that some controllers * will then treat the 8 bit command words as 12 bits (and drop the * four MSBs of the 12 bit result). Result: inputs must be shifted @@ -596,6 +609,7 @@ static int __devinit ads7846_probe(struct spi_device *spi) ts->x_plate_ohms = pdata->x_plate_ohms ? : 400; ts->debounce_max = pdata->debounce_max ? : 1; ts->debounce_tol = pdata->debounce_tol ? : 10; + ts->get_pendown_state = pdata->get_pendown_state; snprintf(ts->phys, sizeof(ts->phys), "%s/input0", spi->dev.bus_id); @@ -786,8 +800,8 @@ static int __devexit ads7846_remove(struct spi_device *spi) device_remove_file(&spi->dev, &dev_attr_vaux); free_irq(ts->spi->irq, ts); - if (ts->irq_disabled) - enable_irq(ts->spi->irq); + /* suspend left the IRQ disabled */ + enable_irq(ts->spi->irq); kfree(ts); -- cgit v1.2.3-18-g5258 From 20ac94378de59d61dc39f10ed5530485e4ac8c07 Mon Sep 17 00:00:00 2001 From: "Eric W. Biederman" Date: Thu, 13 Apr 2006 04:49:07 -0600 Subject: [PATCH] do_SAK: Don't recursively take the tasklist_lock By calling send_sig do_SAK is recursively taking the tasklist_lock, which is silly. In addition I just audited the kernel and this was the only place where tasklist_lock is taken inside of task_lock. So this one line change is a general worthwhile cleanup and it increases our options on how to fix the ptrace_attach races. Signed-off-by: Linus Torvalds --- drivers/char/tty_io.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'drivers') diff --git a/drivers/char/tty_io.c b/drivers/char/tty_io.c index f70a47eadb5..841f0bd3eaa 100644 --- a/drivers/char/tty_io.c +++ b/drivers/char/tty_io.c @@ -2734,7 +2734,7 @@ static void __do_SAK(void *arg) printk(KERN_NOTICE "SAK: killed process %d" " (%s): fd#%d opened to the tty\n", p->pid, p->comm, i); - send_sig(SIGKILL, p, 1); + force_sig(SIGKILL, p); break; } } -- cgit v1.2.3-18-g5258 From 950ee4c8f094feecd3add994a2cf4fd335ca509b Mon Sep 17 00:00:00 2001 From: Guennadi Liakhovetski Date: Sun, 19 Mar 2006 20:49:14 +0100 Subject: [PATCH] USB: net2282 and net2280 software compatibility Below is a patch to gadgets/net2280.[ch] which adds support for the net2282 controller. The original code was kindly provided by PLX Technology, I just merged it with the current net2280 driver in the kernel. Tested on 2.6.15.6, but only with 2282. I did the merge, so that the behaviour for the 2280 is unaffected (except for short delays for extra checks). Signed-off-by: G. Liakhovetski Signed-off-by: Greg Kroah-Hartman Support for net2282 in net2280 driver. --- drivers/usb/gadget/Kconfig | 4 +- drivers/usb/gadget/net2280.c | 90 +++++++++++++++++++++++++++++++++----------- drivers/usb/gadget/net2280.h | 2 + 3 files changed, 73 insertions(+), 23 deletions(-) (limited to 'drivers') diff --git a/drivers/usb/gadget/Kconfig b/drivers/usb/gadget/Kconfig index d80f71877d6..363b2ad74ae 100644 --- a/drivers/usb/gadget/Kconfig +++ b/drivers/usb/gadget/Kconfig @@ -69,11 +69,11 @@ choice often need board-specific hooks. config USB_GADGET_NET2280 - boolean "NetChip 2280" + boolean "NetChip 228x" depends on PCI select USB_GADGET_DUALSPEED help - NetChip 2280 is a PCI based USB peripheral controller which + NetChip 2280 / 2282 is a PCI based USB peripheral controller which supports both full and high speed USB 2.0 data transfers. It has six configurable endpoints, as well as endpoint zero diff --git a/drivers/usb/gadget/net2280.c b/drivers/usb/gadget/net2280.c index fb73dc10053..7682c07035b 100644 --- a/drivers/usb/gadget/net2280.c +++ b/drivers/usb/gadget/net2280.c @@ -26,6 +26,8 @@ * Copyright (C) 2003 David Brownell * Copyright (C) 2003-2005 PLX Technology, Inc. * + * Modified Seth Levy 2005 PLX Technology, Inc. to provide compatibility with 2282 chip + * * 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; either version 2 of the License, or @@ -71,8 +73,8 @@ #include -#define DRIVER_DESC "PLX NET2280 USB Peripheral Controller" -#define DRIVER_VERSION "2005 Feb 03" +#define DRIVER_DESC "PLX NET228x USB Peripheral Controller" +#define DRIVER_VERSION "2005 Sept 27" #define DMA_ADDR_INVALID (~(dma_addr_t)0) #define EP_DONTUSE 13 /* nonzero */ @@ -118,7 +120,7 @@ module_param (fifo_mode, ushort, 0644); /* enable_suspend -- When enabled, the driver will respond to * USB suspend requests by powering down the NET2280. Otherwise, * USB suspend requests will be ignored. This is acceptible for - * self-powered devices, and helps avoid some quirks. + * self-powered devices */ static int enable_suspend = 0; @@ -223,6 +225,11 @@ net2280_enable (struct usb_ep *_ep, const struct usb_endpoint_descriptor *desc) ep->is_in = (tmp & USB_DIR_IN) != 0; if (!ep->is_in) writel ((1 << SET_NAK_OUT_PACKETS), &ep->regs->ep_rsp); + else if (dev->pdev->device != 0x2280) { + /* Added for 2282, Don't use nak packets on an in endpoint, this was ignored on 2280 */ + writel ((1 << CLEAR_NAK_OUT_PACKETS) + | (1 << CLEAR_NAK_OUT_PACKETS_MODE), &ep->regs->ep_rsp); + } writel (tmp, &ep->regs->ep_cfg); @@ -232,8 +239,9 @@ net2280_enable (struct usb_ep *_ep, const struct usb_endpoint_descriptor *desc) writel (tmp, &dev->regs->pciirqenb0); tmp = (1 << DATA_PACKET_RECEIVED_INTERRUPT_ENABLE) - | (1 << DATA_PACKET_TRANSMITTED_INTERRUPT_ENABLE) - | readl (&ep->regs->ep_irqenb); + | (1 << DATA_PACKET_TRANSMITTED_INTERRUPT_ENABLE); + if (dev->pdev->device == 0x2280) + tmp |= readl (&ep->regs->ep_irqenb); writel (tmp, &ep->regs->ep_irqenb); } else { /* dma, per-request */ tmp = (1 << (8 + ep->num)); /* completion */ @@ -314,10 +322,18 @@ static void ep_reset (struct net2280_regs __iomem *regs, struct net2280_ep *ep) /* init to our chosen defaults, notably so that we NAK OUT * packets until the driver queues a read (+note erratum 0112) */ - tmp = (1 << SET_NAK_OUT_PACKETS_MODE) + if (!ep->is_in || ep->dev->pdev->device == 0x2280) { + tmp = (1 << SET_NAK_OUT_PACKETS_MODE) | (1 << SET_NAK_OUT_PACKETS) | (1 << CLEAR_EP_HIDE_STATUS_PHASE) | (1 << CLEAR_INTERRUPT_MODE); + } else { + /* added for 2282 */ + tmp = (1 << CLEAR_NAK_OUT_PACKETS_MODE) + | (1 << CLEAR_NAK_OUT_PACKETS) + | (1 << CLEAR_EP_HIDE_STATUS_PHASE) + | (1 << CLEAR_INTERRUPT_MODE); + } if (ep->num != 0) { tmp |= (1 << CLEAR_ENDPOINT_TOGGLE) @@ -326,14 +342,18 @@ static void ep_reset (struct net2280_regs __iomem *regs, struct net2280_ep *ep) writel (tmp, &ep->regs->ep_rsp); /* scrub most status bits, and flush any fifo state */ - writel ( (1 << TIMEOUT) + if (ep->dev->pdev->device == 0x2280) + tmp = (1 << FIFO_OVERFLOW) + | (1 << FIFO_UNDERFLOW); + else + tmp = 0; + + writel (tmp | (1 << TIMEOUT) | (1 << USB_STALL_SENT) | (1 << USB_IN_NAK_SENT) | (1 << USB_IN_ACK_RCVD) | (1 << USB_OUT_PING_NAK_SENT) | (1 << USB_OUT_ACK_SENT) - | (1 << FIFO_OVERFLOW) - | (1 << FIFO_UNDERFLOW) | (1 << FIFO_FLUSH) | (1 << SHORT_PACKET_OUT_DONE_INTERRUPT) | (1 << SHORT_PACKET_TRANSFERRED_INTERRUPT) @@ -718,7 +738,7 @@ fill_dma_desc (struct net2280_ep *ep, struct net2280_request *req, int valid) */ if (ep->is_in) dmacount |= (1 << DMA_DIRECTION); - else if ((dmacount % ep->ep.maxpacket) != 0) + if ((!ep->is_in && (dmacount % ep->ep.maxpacket) != 0) || ep->dev->pdev->device != 0x2280) dmacount |= (1 << END_OF_CHAIN); req->valid = valid; @@ -760,9 +780,12 @@ static inline void stop_dma (struct net2280_dma_regs __iomem *dma) static void start_queue (struct net2280_ep *ep, u32 dmactl, u32 td_dma) { struct net2280_dma_regs __iomem *dma = ep->dma; + unsigned int tmp = (1 << VALID_BIT) | (ep->is_in << DMA_DIRECTION); - writel ((1 << VALID_BIT) | (ep->is_in << DMA_DIRECTION), - &dma->dmacount); + if (ep->dev->pdev->device != 0x2280) + tmp |= (1 << END_OF_CHAIN); + + writel (tmp, &dma->dmacount); writel (readl (&dma->dmastat), &dma->dmastat); writel (td_dma, &dma->dmadesc); @@ -2110,7 +2133,11 @@ static void handle_ep_small (struct net2280_ep *ep) VDEBUG (ep->dev, "%s ack ep_stat %08x, req %p\n", ep->ep.name, t, req ? &req->req : 0); #endif - writel (t & ~(1 << NAK_OUT_PACKETS), &ep->regs->ep_stat); + if (!ep->is_in || ep->dev->pdev->device == 0x2280) + writel (t & ~(1 << NAK_OUT_PACKETS), &ep->regs->ep_stat); + else + /* Added for 2282 */ + writel (t, &ep->regs->ep_stat); /* for ep0, monitor token irqs to catch data stage length errors * and to synchronize on status. @@ -2337,7 +2364,7 @@ static void handle_stat0_irqs (struct net2280 *dev, u32 stat) u32 raw [2]; struct usb_ctrlrequest r; } u; - int tmp = 0; + int tmp; struct net2280_request *req; if (dev->gadget.speed == USB_SPEED_UNKNOWN) { @@ -2364,14 +2391,19 @@ static void handle_stat0_irqs (struct net2280 *dev, u32 stat) } ep->stopped = 0; dev->protocol_stall = 0; - writel ( (1 << TIMEOUT) + + if (ep->dev->pdev->device == 0x2280) + tmp = (1 << FIFO_OVERFLOW) + | (1 << FIFO_UNDERFLOW); + else + tmp = 0; + + writel (tmp | (1 << TIMEOUT) | (1 << USB_STALL_SENT) | (1 << USB_IN_NAK_SENT) | (1 << USB_IN_ACK_RCVD) | (1 << USB_OUT_PING_NAK_SENT) | (1 << USB_OUT_ACK_SENT) - | (1 << FIFO_OVERFLOW) - | (1 << FIFO_UNDERFLOW) | (1 << SHORT_PACKET_OUT_DONE_INTERRUPT) | (1 << SHORT_PACKET_TRANSFERRED_INTERRUPT) | (1 << DATA_PACKET_RECEIVED_INTERRUPT) @@ -2385,6 +2417,8 @@ static void handle_stat0_irqs (struct net2280 *dev, u32 stat) cpu_to_le32s (&u.raw [0]); cpu_to_le32s (&u.raw [1]); + tmp = 0; + #define w_value le16_to_cpup (&u.r.wValue) #define w_index le16_to_cpup (&u.r.wIndex) #define w_length le16_to_cpup (&u.r.wLength) @@ -2594,10 +2628,17 @@ static void handle_stat1_irqs (struct net2280 *dev, u32 stat) writel (stat, &dev->regs->irqstat1); /* some status we can just ignore */ - stat &= ~((1 << CONTROL_STATUS_INTERRUPT) - | (1 << SUSPEND_REQUEST_INTERRUPT) - | (1 << RESUME_INTERRUPT) - | (1 << SOF_INTERRUPT)); + if (dev->pdev->device == 0x2280) + stat &= ~((1 << CONTROL_STATUS_INTERRUPT) + | (1 << SUSPEND_REQUEST_INTERRUPT) + | (1 << RESUME_INTERRUPT) + | (1 << SOF_INTERRUPT)); + else + stat &= ~((1 << CONTROL_STATUS_INTERRUPT) + | (1 << RESUME_INTERRUPT) + | (1 << SOF_DOWN_INTERRUPT) + | (1 << SOF_INTERRUPT)); + if (!stat) return; // DEBUG (dev, "irqstat1 %08x\n", stat); @@ -2939,6 +2980,13 @@ static struct pci_device_id pci_ids [] = { { .device = 0x2280, .subvendor = PCI_ANY_ID, .subdevice = PCI_ANY_ID, +}, { + .class = ((PCI_CLASS_SERIAL_USB << 8) | 0xfe), + .class_mask = ~0, + .vendor = 0x17cc, + .device = 0x2282, + .subvendor = PCI_ANY_ID, + .subdevice = PCI_ANY_ID, }, { /* end: all zeroes */ } }; diff --git a/drivers/usb/gadget/net2280.h b/drivers/usb/gadget/net2280.h index fff4509cf34..e195abec8d7 100644 --- a/drivers/usb/gadget/net2280.h +++ b/drivers/usb/gadget/net2280.h @@ -179,6 +179,7 @@ struct net2280_regs { #define PCI_TARGET_ABORT_RECEIVED_INTERRUPT 19 #define PCI_RETRY_ABORT_INTERRUPT 17 #define PCI_MASTER_CYCLE_DONE_INTERRUPT 16 +#define SOF_DOWN_INTERRUPT 14 #define GPIO_INTERRUPT 13 #define DMA_D_INTERRUPT 12 #define DMA_C_INTERRUPT 11 @@ -346,6 +347,7 @@ struct net2280_dma_regs { /* [11.7] */ #define DMA_ENABLE 1 #define DMA_ADDRESS_HOLD 0 u32 dmastat; +#define DMA_ABORT_DONE_INTERRUPT 27 #define DMA_SCATTER_GATHER_DONE_INTERRUPT 25 #define DMA_TRANSACTION_DONE_INTERRUPT 24 #define DMA_ABORT 1 -- cgit v1.2.3-18-g5258 From f096e0434c717d7a2aa1614e0be0d1b7c64bec29 Mon Sep 17 00:00:00 2001 From: Ben Dooks Date: Tue, 21 Mar 2006 22:54:47 +0000 Subject: [PATCH] USB: cleanups for ohci-s3c2410.c Fix compile errors due to functions not being defined static Signed-off-by: Ben Dooks Signed-off-by: Greg Kroah-Hartman --- drivers/usb/host/ohci-s3c2410.c | 9 +++++---- 1 file changed, 5 insertions(+), 4 deletions(-) (limited to 'drivers') diff --git a/drivers/usb/host/ohci-s3c2410.c b/drivers/usb/host/ohci-s3c2410.c index 682bf221566..b27669fe9f0 100644 --- a/drivers/usb/host/ohci-s3c2410.c +++ b/drivers/usb/host/ohci-s3c2410.c @@ -37,7 +37,7 @@ static void s3c2410_hcd_oc(struct s3c2410_hcd_info *info, int port_oc); /* conversion functions */ -struct s3c2410_hcd_info *to_s3c2410_info(struct usb_hcd *hcd) +static struct s3c2410_hcd_info *to_s3c2410_info(struct usb_hcd *hcd) { return hcd->self.controller->platform_data; } @@ -316,7 +316,8 @@ static void s3c2410_hcd_oc(struct s3c2410_hcd_info *info, int port_oc) * */ -void usb_hcd_s3c2410_remove (struct usb_hcd *hcd, struct platform_device *dev) +static void +usb_hcd_s3c2410_remove (struct usb_hcd *hcd, struct platform_device *dev) { usb_remove_hcd(hcd); s3c2410_stop_hc(dev); @@ -334,8 +335,8 @@ void usb_hcd_s3c2410_remove (struct usb_hcd *hcd, struct platform_device *dev) * through the hotplug entry's driver_data. * */ -int usb_hcd_s3c2410_probe (const struct hc_driver *driver, - struct platform_device *dev) +static int usb_hcd_s3c2410_probe (const struct hc_driver *driver, + struct platform_device *dev) { struct usb_hcd *hcd = NULL; int retval; -- cgit v1.2.3-18-g5258 From 7e1c0b86aca9d42fa4de3fdad17c57bb462fe1e2 Mon Sep 17 00:00:00 2001 From: Ian Abbott Date: Tue, 21 Mar 2006 14:55:20 +0000 Subject: [PATCH] USB: ftdi_sio: add support for Eclo COM to 1-Wire USB adapter This patch adds support for the Eclo COM to 1-Wire USB adapter to the ftdi_sio driver's device ID table. Details were provided by Martin Grill on the ftdi-sio-usb-devel mailing list and I (Ian Abbott) confirmed it matched the INF file in the Eclo's Windows driver package. Signed-off-by: Ian Abbott Signed-off-by: Greg Kroah-Hartman --- drivers/usb/serial/ftdi_sio.c | 1 + drivers/usb/serial/ftdi_sio.h | 6 ++++++ 2 files changed, 7 insertions(+) (limited to 'drivers') diff --git a/drivers/usb/serial/ftdi_sio.c b/drivers/usb/serial/ftdi_sio.c index f3af81b4dd2..67793d9ca5f 100644 --- a/drivers/usb/serial/ftdi_sio.c +++ b/drivers/usb/serial/ftdi_sio.c @@ -489,6 +489,7 @@ static struct usb_device_id id_table_combined [] = { { USB_DEVICE(KOBIL_VID, KOBIL_CONV_KAAN_PID) }, { USB_DEVICE(POSIFLEX_VID, POSIFLEX_PP7000_PID) }, { USB_DEVICE(FTDI_VID, FTDI_TTUSB_PID) }, + { USB_DEVICE(FTDI_VID, FTDI_ECLO_COM_1WIRE_PID) }, { USB_DEVICE(FTDI_VID, FTDI_WESTREX_MODEL_777_PID) }, { USB_DEVICE(FTDI_VID, FTDI_WESTREX_MODEL_8900F_PID) }, { USB_DEVICE(FTDI_VID, FTDI_PCDJ_DAC2_PID) }, diff --git a/drivers/usb/serial/ftdi_sio.h b/drivers/usb/serial/ftdi_sio.h index 8da773c2744..18bcc3ab4d2 100644 --- a/drivers/usb/serial/ftdi_sio.h +++ b/drivers/usb/serial/ftdi_sio.h @@ -399,6 +399,12 @@ #define FTDI_WESTREX_MODEL_777_PID 0xDC00 /* Model 777 */ #define FTDI_WESTREX_MODEL_8900F_PID 0xDC01 /* Model 8900F */ +/* + * Eclo (http://www.eclo.pt/) product IDs. + * PID 0xEA90 submitted by Martin Grill. + */ +#define FTDI_ECLO_COM_1WIRE_PID 0xEA90 /* COM to 1-Wire USB adaptor */ + /* Commands */ #define FTDI_SIO_RESET 0 /* Reset the port */ #define FTDI_SIO_MODEM_CTRL 1 /* Set the modem control register */ -- cgit v1.2.3-18-g5258 From 70ffe6e14d7c5db84b92841471ce6fd0200010cd Mon Sep 17 00:00:00 2001 From: Alan Stern Date: Thu, 23 Mar 2006 15:05:16 -0500 Subject: [PATCH] USB: g_file_storage: Set short_not_ok for bulk-out transfers I'm told that some UDC hardware may work better if it knows that receiving a short packet should always cause an error. Accordingly, this patch (as663) sets the short_not_ok flag for bulk-out transfers in g_file_storage. Oddly enough, there are no circumstances where that driver can legally receive a shorter-than-expected bulk-out packet. Signed-off-by: Alan Stern Signed-off-by: Greg Kroah-Hartman --- drivers/usb/gadget/file_storage.c | 3 +++ 1 file changed, 3 insertions(+) (limited to 'drivers') diff --git a/drivers/usb/gadget/file_storage.c b/drivers/usb/gadget/file_storage.c index cf3be299e35..eb2821542b7 100644 --- a/drivers/usb/gadget/file_storage.c +++ b/drivers/usb/gadget/file_storage.c @@ -1795,6 +1795,7 @@ static int do_write(struct fsg_dev *fsg) * the bulk-out maxpacket size */ bh->outreq->length = bh->bulk_out_intended_length = amount; + bh->outreq->short_not_ok = 1; start_transfer(fsg, fsg->bulk_out, bh->outreq, &bh->outreq_busy, &bh->state); fsg->next_buffhd_to_fill = bh->next; @@ -2398,6 +2399,7 @@ static int throw_away_data(struct fsg_dev *fsg) * the bulk-out maxpacket size */ bh->outreq->length = bh->bulk_out_intended_length = amount; + bh->outreq->short_not_ok = 1; start_transfer(fsg, f