From cf417141cbb3a4ceb5cca15b2c1f099bd0a6603c Mon Sep 17 00:00:00 2001 From: Max Krasnyansky Date: Mon, 11 Aug 2008 14:33:53 -0700 Subject: sched, cpuset: rework sched domains and CPU hotplug handling (v4) This is an updated version of my previous cpuset patch on top of the latest mainline git. The patch fixes CPU hotplug handling issues in the current cpusets code. Namely circular locking in rebuild_sched_domains() and unsafe access to the cpu_online_map in the cpuset cpu hotplug handler. This version includes changes suggested by Paul Jackson (naming, comments, style, etc). I also got rid of the separate workqueue thread because it is now safe to call get_online_cpus() from workqueue callbacks. Here are some more details: rebuild_sched_domains() is the only way to rebuild sched domains correctly based on the current cpuset settings. What this means is that we need to be able to call it from different contexts, like cpu hotplug for example. Also latest scheduler code in -tip now calls rebuild_sched_domains() directly from functions like arch_reinit_sched_domains(). In order to support that properly we need to rework cpuset locking rules to avoid circular dependencies, which is what this patch does. New lock nesting rules are explained in the comments. We can now safely call rebuild_sched_domains() from virtually any context. The only requirement is that it needs to be called under get_online_cpus(). This allows cpu hotplug handlers and the scheduler to call rebuild_sched_domains() directly. The rest of the cpuset code now offloads sched domains rebuilds to a workqueue (async_rebuild_sched_domains()). This version of the patch addresses comments from the previous review. I fixed all miss-formated comments and trailing spaces. I also factored out the code that builds domain masks and split up CPU and memory hotplug handling. This was needed to simplify locking, to avoid unsafe access to the cpu_online_map from mem hotplug handler, and in general to make things cleaner. The patch passes moderate testing (building kernel with -j 16, creating & removing domains and bringing cpus off/online at the same time) on the quad-core2 based machine. It passes lockdep checks, even with preemptable RCU enabled. This time I also tested in with suspend/resume path and everything is working as expected. Signed-off-by: Max Krasnyansky Acked-by: Paul Jackson Cc: menage@google.com Cc: a.p.zijlstra@chello.nl Cc: vegard.nossum@gmail.com Signed-off-by: Ingo Molnar diff --git a/kernel/cpuset.c b/kernel/cpuset.c index d5ab79c..f227bc1 100644 --- a/kernel/cpuset.c +++ b/kernel/cpuset.c @@ -14,6 +14,8 @@ * 2003-10-22 Updates by Stephen Hemminger. * 2004 May-July Rework by Paul Jackson. * 2006 Rework by Paul Menage to use generic cgroups + * 2008 Rework of the scheduler domains and CPU hotplug handling + * by Max Krasnyansky * * This file is subject to the terms and conditions of the GNU General Public * License. See the file COPYING in the main directory of the Linux @@ -236,9 +238,11 @@ static struct cpuset top_cpuset = { static DEFINE_MUTEX(callback_mutex); -/* This is ugly, but preserves the userspace API for existing cpuset +/* + * This is ugly, but preserves the userspace API for existing cpuset * users. If someone tries to mount the "cpuset" filesystem, we - * silently switch it to mount "cgroup" instead */ + * silently switch it to mount "cgroup" instead + */ static int cpuset_get_sb(struct file_system_type *fs_type, int flags, const char *unused_dev_name, void *data, struct vfsmount *mnt) @@ -473,10 +477,9 @@ static int validate_change(const struct cpuset *cur, const struct cpuset *trial) } /* - * Helper routine for rebuild_sched_domains(). + * Helper routine for generate_sched_domains(). * Do cpusets a, b have overlapping cpus_allowed masks? */ - static int cpusets_overlap(struct cpuset *a, struct cpuset *b) { return cpus_intersects(a->cpus_allowed, b->cpus_allowed); @@ -518,26 +521,15 @@ update_domain_attr_tree(struct sched_domain_attr *dattr, struct cpuset *c) } /* - * rebuild_sched_domains() - * - * This routine will be called to rebuild the scheduler's dynamic - * sched domains: - * - if the flag 'sched_load_balance' of any cpuset with non-empty - * 'cpus' changes, - * - or if the 'cpus' allowed changes in any cpuset which has that - * flag enabled, - * - or if the 'sched_relax_domain_level' of any cpuset which has - * that flag enabled and with non-empty 'cpus' changes, - * - or if any cpuset with non-empty 'cpus' is removed, - * - or if a cpu gets offlined. - * - * This routine builds a partial partition of the systems CPUs - * (the set of non-overlappping cpumask_t's in the array 'part' - * below), and passes that partial partition to the kernel/sched.c - * partition_sched_domains() routine, which will rebuild the - * schedulers load balancing domains (sched domains) as specified - * by that partial partition. A 'partial partition' is a set of - * non-overlapping subsets whose union is a subset of that set. + * generate_sched_domains() + * + * This function builds a partial partition of the systems CPUs + * A 'partial partition' is a set of non-overlapping subsets whose + * union is a subset of that set. + * The output of this function needs to be passed to kernel/sched.c + * partition_sched_domains() routine, which will rebuild the scheduler's + * load balancing domains (sched domains) as specified by that partial + * partition. * * See "What is sched_load_balance" in Documentation/cpusets.txt * for a background explanation of this. @@ -547,13 +539,7 @@ update_domain_attr_tree(struct sched_domain_attr *dattr, struct cpuset *c) * domains when operating in the severe memory shortage situations * that could cause allocation failures below. * - * Call with cgroup_mutex held. May take callback_mutex during - * call due to the kfifo_alloc() and kmalloc() calls. May nest - * a call to the get_online_cpus()/put_online_cpus() pair. - * Must not be called holding callback_mutex, because we must not - * call get_online_cpus() while holding callback_mutex. Elsewhere - * the kernel nests callback_mutex inside get_online_cpus() calls. - * So the reverse nesting would risk an ABBA deadlock. + * Must be called with cgroup_lock held. * * The three key local variables below are: * q - a linked-list queue of cpuset pointers, used to implement a @@ -588,10 +574,10 @@ update_domain_attr_tree(struct sched_domain_attr *dattr, struct cpuset *c) * element of the partition (one sched domain) to be passed to * partition_sched_domains(). */ - -void rebuild_sched_domains(void) +static int generate_sched_domains(cpumask_t **domains, + struct sched_domain_attr **attributes) { - LIST_HEAD(q); /* queue of cpusets to be scanned*/ + LIST_HEAD(q); /* queue of cpusets to be scanned */ struct cpuset *cp; /* scans q */ struct cpuset **csa; /* array of all cpuset ptrs */ int csn; /* how many cpuset ptrs in csa so far */ @@ -601,23 +587,26 @@ void rebuild_sched_domains(void) int ndoms; /* number of sched domains in result */ int nslot; /* next empty doms[] cpumask_t slot */ - csa = NULL; + ndoms = 0; doms = NULL; dattr = NULL; + csa = NULL; /* Special case for the 99% of systems with one, full, sched domain */ if (is_sched_load_balance(&top_cpuset)) { - ndoms = 1; doms = kmalloc(sizeof(cpumask_t), GFP_KERNEL); if (!doms) - goto rebuild; + goto done; + dattr = kmalloc(sizeof(struct sched_domain_attr), GFP_KERNEL); if (dattr) { *dattr = SD_ATTR_INIT; update_domain_attr_tree(dattr, &top_cpuset); } *doms = top_cpuset.cpus_allowed; - goto rebuild; + + ndoms = 1; + goto done; } csa = kmalloc(number_of_cpusets * sizeof(cp), GFP_KERNEL); @@ -680,61 +669,141 @@ restart: } } - /* Convert to */ + /* + * Now we know how many domains to create. + * Convert to and populate cpu masks. + */ doms = kmalloc(ndoms * sizeof(cpumask_t), GFP_KERNEL); - if (!doms) - goto rebuild; + if (!doms) { + ndoms = 0; + goto done; + } + + /* + * The rest of the code, including the scheduler, can deal with + * dattr==NULL case. No need to abort if alloc fails. + */ dattr = kmalloc(ndoms * sizeof(struct sched_domain_attr), GFP_KERNEL); for (nslot = 0, i = 0; i < csn; i++) { struct cpuset *a = csa[i]; + cpumask_t *dp; int apn = a->pn; - if (apn >= 0) { - cpumask_t *dp = doms + nslot; - - if (nslot == ndoms) { - static int warnings = 10; - if (warnings) { - printk(KERN_WARNING - "rebuild_sched_domains confused:" - " nslot %d, ndoms %d, csn %d, i %d," - " apn %d\n", - nslot, ndoms, csn, i, apn); - warnings--; - } - continue; + if (apn < 0) { + /* Skip completed partitions */ + continue; + } + + dp = doms + nslot; + + if (nslot == ndoms) { + static int warnings = 10; + if (warnings) { + printk(KERN_WARNING + "rebuild_sched_domains confused:" + " nslot %d, ndoms %d, csn %d, i %d," + " apn %d\n", + nslot, ndoms, csn, i, apn); + warnings--; } + continue; + } - cpus_clear(*dp); - if (dattr) - *(dattr + nslot) = SD_ATTR_INIT; - for (j = i; j < csn; j++) { - struct cpuset *b = csa[j]; - - if (apn == b->pn) { - cpus_or(*dp, *dp, b->cpus_allowed); - b->pn = -1; - if (dattr) - update_domain_attr_tree(dattr - + nslot, b); - } + cpus_clear(*dp); + if (dattr) + *(dattr + nslot) = SD_ATTR_INIT; + for (j = i; j < csn; j++) { + struct cpuset *b = csa[j]; + + if (apn == b->pn) { + cpus_or(*dp, *dp, b->cpus_allowed); + if (dattr) + update_domain_attr_tree(dattr + nslot, b); + + /* Done with this partition */ + b->pn = -1; } - nslot++; } + nslot++; } BUG_ON(nslot != ndoms); -rebuild: - /* Have scheduler rebuild sched domains */ +done: + kfree(csa); + + *domains = doms; + *attributes = dattr; + return ndoms; +} + +/* + * Rebuild scheduler domains. + * + * Call with neither cgroup_mutex held nor within get_online_cpus(). + * Takes both cgroup_mutex and get_online_cpus(). + * + * Cannot be directly called from cpuset code handling changes + * to the cpuset pseudo-filesystem, because it cannot be called + * from code that already holds cgroup_mutex. + */ +static void do_rebuild_sched_domains(struct work_struct *unused) +{ + struct sched_domain_attr *attr; + cpumask_t *doms; + int ndoms; + get_online_cpus(); - partition_sched_domains(ndoms, doms, dattr); + + /* Generate domain masks and attrs */ + cgroup_lock(); + ndoms = generate_sched_domains(&doms, &attr); + cgroup_unlock(); + + /* Have scheduler rebuild the domains */ + partition_sched_domains(ndoms, doms, attr); + put_online_cpus(); +} -done: - kfree(csa); - /* Don't kfree(doms) -- partition_sched_domains() does that. */ - /* Don't kfree(dattr) -- partition_sched_domains() does that. */ +static DECLARE_WORK(rebuild_sched_domains_work, do_rebuild_sched_domains); + +/* + * Rebuild scheduler domains, asynchronously via workqueue. + * + * If the flag 'sched_load_balance' of any cpuset with non-empty + * 'cpus' changes, or if the 'cpus' allowed changes in any cpuset + * which has that flag enabled, or if any cpuset with a non-empty + * 'cpus' is removed, then call this routine to rebuild the + * scheduler's dynamic sched domains. + * + * The rebuild_sched_domains() and partition_sched_domains() + * routines must nest cgroup_lock() inside get_online_cpus(), + * but such cpuset changes as these must nest that locking the + * other way, holding cgroup_lock() for much of the code. + * + * So in order to avoid an ABBA deadlock, the cpuset code handling + * these user changes delegates the actual sched domain rebuilding + * to a separate workqueue thread, which ends up processing the + * above do_rebuild_sched_domains() function. + */ +static void async_rebuild_sched_domains(void) +{ + schedule_work(&rebuild_sched_domains_work); +} + +/* + * Accomplishes the same scheduler domain rebuild as the above + * async_rebuild_sched_domains(), however it directly calls the + * rebuild routine synchronously rather than calling it via an + * asynchronous work thread. + * + * This can only be called from code that is not holding + * cgroup_mutex (not nested in a cgroup_lock() call.) + */ +void rebuild_sched_domains(void) +{ + do_rebuild_sched_domains(NULL); } /** @@ -863,7 +932,7 @@ static int update_cpumask(struct cpuset *cs, const char *buf) return retval; if (is_load_balanced) - rebuild_sched_domains(); + async_rebuild_sched_domains(); return 0; } @@ -1090,7 +1159,7 @@ static int update_relax_domain_level(struct cpuset *cs, s64 val) if (val != cs->relax_domain_level) { cs->relax_domain_level = val; if (!cpus_empty(cs->cpus_allowed) && is_sched_load_balance(cs)) - rebuild_sched_domains(); + async_rebuild_sched_domains(); } return 0; @@ -1131,7 +1200,7 @@ static int update_flag(cpuset_flagbits_t bit, struct cpuset *cs, mutex_unlock(&callback_mutex); if (cpus_nonempty && balance_flag_changed) - rebuild_sched_domains(); + async_rebuild_sched_domains(); return 0; } @@ -1492,6 +1561,9 @@ static u64 cpuset_read_u64(struct cgroup *cont, struct cftype *cft) default: BUG(); } + + /* Unreachable but makes gcc happy */ + return 0; } static s64 cpuset_read_s64(struct cgroup *cont, struct cftype *cft) @@ -1504,6 +1576,9 @@ static s64 cpuset_read_s64(struct cgroup *cont, struct cftype *cft) default: BUG(); } + + /* Unrechable but makes gcc happy */ + return 0; } @@ -1692,15 +1767,9 @@ static struct cgroup_subsys_state *cpuset_create( } /* - * Locking note on the strange update_flag() call below: - * * If the cpuset being removed has its flag 'sched_load_balance' * enabled, then simulate turning sched_load_balance off, which - * will call rebuild_sched_domains(). The get_online_cpus() - * call in rebuild_sched_domains() must not be made while holding - * callback_mutex. Elsewhere the kernel nests callback_mutex inside - * get_online_cpus() calls. So the reverse nesting would risk an - * ABBA deadlock. + * will call async_rebuild_sched_domains(). */ static void cpuset_destroy(struct cgroup_subsys *ss, struct cgroup *cont) @@ -1719,7 +1788,7 @@ static void cpuset_destroy(struct cgroup_subsys *ss, struct cgroup *cont) struct cgroup_subsys cpuset_subsys = { .name = "cpuset", .create = cpuset_create, - .destroy = cpuset_destroy, + .destroy = cpuset_destroy, .can_attach = cpuset_can_attach, .attach = cpuset_attach, .populate = cpuset_populate, @@ -1811,7 +1880,7 @@ static void move_member_tasks_to_cpuset(struct cpuset *from, struct cpuset *to) } /* - * If common_cpu_mem_hotplug_unplug(), below, unplugs any CPUs + * If CPU and/or memory hotplug handlers, below, unplug any CPUs * or memory nodes, we need to walk over the cpuset hierarchy, * removing that CPU or node from all cpusets. If this removes the * last CPU or node from a cpuset, then move the tasks in the empty @@ -1903,35 +1972,6 @@ static void scan_for_empty_cpusets(const struct cpuset *root) } /* - * The cpus_allowed and mems_allowed nodemasks in the top_cpuset track - * cpu_online_map and node_states[N_HIGH_MEMORY]. Force the top cpuset to - * track what's online after any CPU or memory node hotplug or unplug event. - * - * Since there are two callers of this routine, one for CPU hotplug - * events and one for memory node hotplug events, we could have coded - * two separate routines here. We code it as a single common routine - * in order to minimize text size. - */ - -static void common_cpu_mem_hotplug_unplug(int rebuild_sd) -{ - cgroup_lock(); - - top_cpuset.cpus_allowed = cpu_online_map; - top_cpuset.mems_allowed = node_states[N_HIGH_MEMORY]; - scan_for_empty_cpusets(&top_cpuset); - - /* - * Scheduler destroys domains on hotplug events. - * Rebuild them based on the current settings. - */ - if (rebuild_sd) - rebuild_sched_domains(); - - cgroup_unlock(); -} - -/* * The top_cpuset tracks what CPUs and Memory Nodes are online, * period. This is necessary in order to make cpusets transparent * (of no affect) on systems that are actively using CPU hotplug @@ -1939,40 +1979,52 @@ static void common_cpu_mem_hotplug_unplug(int rebuild_sd) * * This routine ensures that top_cpuset.cpus_allowed tracks * cpu_online_map on each CPU hotplug (cpuhp) event. + * + * Called within get_online_cpus(). Needs to call cgroup_lock() + * before calling generate_sched_domains(). */ - -static int cpuset_handle_cpuhp(struct notifier_block *unused_nb, +static int cpuset_track_online_cpus(struct notifier_block *unused_nb, unsigned long phase, void *unused_cpu) { + struct sched_domain_attr *attr; + cpumask_t *doms; + int ndoms; + switch (phase) { - case CPU_UP_CANCELED: - case CPU_UP_CANCELED_FROZEN: - case CPU_DOWN_FAILED: - case CPU_DOWN_FAILED_FROZEN: case CPU_ONLINE: case CPU_ONLINE_FROZEN: case CPU_DEAD: case CPU_DEAD_FROZEN: - common_cpu_mem_hotplug_unplug(1); break; + default: return NOTIFY_DONE; } + cgroup_lock(); + top_cpuset.cpus_allowed = cpu_online_map; + scan_for_empty_cpusets(&top_cpuset); + ndoms = generate_sched_domains(&doms, &attr); + cgroup_unlock(); + + /* Have scheduler rebuild the domains */ + partition_sched_domains(ndoms, doms, attr); + return NOTIFY_OK; } #ifdef CONFIG_MEMORY_HOTPLUG /* * Keep top_cpuset.mems_allowed tracking node_states[N_HIGH_MEMORY]. - * Call this routine anytime after you change - * node_states[N_HIGH_MEMORY]. - * See also the previous routine cpuset_handle_cpuhp(). + * Call this routine anytime after node_states[N_HIGH_MEMORY] changes. + * See also the previous routine cpuset_track_online_cpus(). */ - void cpuset_track_online_nodes(void) { - common_cpu_mem_hotplug_unplug(0); + cgroup_lock(); + top_cpuset.mems_allowed = node_states[N_HIGH_MEMORY]; + scan_for_empty_cpusets(&top_cpuset); + cgroup_unlock(); } #endif @@ -1987,7 +2039,7 @@ void __init cpuset_init_smp(void) top_cpuset.cpus_allowed = cpu_online_map; top_cpuset.mems_allowed = node_states[N_HIGH_MEMORY]; - hotcpu_notifier(cpuset_handle_cpuhp, 0); + hotcpu_notifier(cpuset_track_online_cpus, 0); } /** -- cgit v0.10.2 From 924e61a90f61b1c22fcb51aaf3afc065399cec81 Mon Sep 17 00:00:00 2001 From: Milan Broz Date: Sat, 16 Aug 2008 02:11:28 +0200 Subject: ACPI: Fix now signed module parameter. Signed-off-by: Milan Broz Signed-off-by: Andi Kleen diff --git a/drivers/acpi/processor_perflib.c b/drivers/acpi/processor_perflib.c index 80e3209..80c251e 100644 --- a/drivers/acpi/processor_perflib.c +++ b/drivers/acpi/processor_perflib.c @@ -71,7 +71,7 @@ static DEFINE_MUTEX(performance_mutex); * 1 -> ignore _PPC totally -> forced by user through boot param */ static int ignore_ppc = -1; -module_param(ignore_ppc, uint, 0644); +module_param(ignore_ppc, int, 0644); MODULE_PARM_DESC(ignore_ppc, "If the frequency of your machine gets wrongly" \ "limited by BIOS, this should help"); -- cgit v0.10.2 From 1371c893ff9de0d57fa5b5cf0255d66b8849e13d Mon Sep 17 00:00:00 2001 From: Ming Ling Date: Mon, 18 Aug 2008 04:14:59 +0200 Subject: ACPI: Change package length error to warning The condition is harmless and no need to scare the user http://bugzilla.kernel.org/show_bug.cgi?id=11245 Signed-off-by: Andi Kleen diff --git a/drivers/acpi/dispatcher/dsobject.c b/drivers/acpi/dispatcher/dsobject.c index 1022e38..0f28058 100644 --- a/drivers/acpi/dispatcher/dsobject.c +++ b/drivers/acpi/dispatcher/dsobject.c @@ -496,7 +496,7 @@ acpi_ds_build_internal_package_obj(struct acpi_walk_state *walk_state, arg = arg->common.next; } - ACPI_ERROR((AE_INFO, + ACPI_WARNING((AE_INFO, "Package List length (%X) larger than NumElements count (%X), truncated\n", i, element_count)); } else if (i < element_count) { -- cgit v0.10.2 From 613e5f3376e48bd48494cf780b79b97b057d49a7 Mon Sep 17 00:00:00 2001 From: Milan Broz Date: Sat, 16 Aug 2008 02:11:28 +0200 Subject: ACPI: Fix now signed module parameter. Signed-off-by: Milan Broz Signed-off-by: Andi Kleen diff --git a/drivers/acpi/processor_perflib.c b/drivers/acpi/processor_perflib.c index 80e3209..80c251e 100644 --- a/drivers/acpi/processor_perflib.c +++ b/drivers/acpi/processor_perflib.c @@ -71,7 +71,7 @@ static DEFINE_MUTEX(performance_mutex); * 1 -> ignore _PPC totally -> forced by user through boot param */ static int ignore_ppc = -1; -module_param(ignore_ppc, uint, 0644); +module_param(ignore_ppc, int, 0644); MODULE_PARM_DESC(ignore_ppc, "If the frequency of your machine gets wrongly" \ "limited by BIOS, this should help"); -- cgit v0.10.2 From 79c4375bf2df96d725475e0c061a4d78c3bd0884 Mon Sep 17 00:00:00 2001 From: Dennis Jansen Date: Wed, 20 Aug 2008 16:44:03 +0200 Subject: ACPI: Fix typo in "Disable MWAIT via DMI on broken Compal board" This fixes a typo in commit 2a2a64714d9c40f7705c4de1e79a5b855c7211a9 "Disable MWAIT via DMI on broken Compal board". It allows the nomwait dmi check to actually detect the Acer 5220. Signed-off-by: Dennis Jansen Tested-by: Dennis Jansen Acked-by: Zhao Yakui Signed-off-by: Andi Kleen diff --git a/drivers/acpi/processor_core.c b/drivers/acpi/processor_core.c index e36422a..499f2fa 100644 --- a/drivers/acpi/processor_core.c +++ b/drivers/acpi/processor_core.c @@ -138,7 +138,7 @@ static struct dmi_system_id __cpuinitdata processor_idle_dmi_table[] = { { set_no_mwait, "Extensa 5220", { DMI_MATCH(DMI_BIOS_VENDOR, "Phoenix Technologies LTD"), - DMI_MATCH(DMI_SYS_VENDOR, "ACER"), + DMI_MATCH(DMI_SYS_VENDOR, "Acer"), DMI_MATCH(DMI_PRODUCT_VERSION, "0100"), DMI_MATCH(DMI_BOARD_NAME, "Columbia") }, NULL}, {}, -- cgit v0.10.2 From f0df2d6b52ad7db5edf56909509d51be66fe90be Mon Sep 17 00:00:00 2001 From: Cyrill Gorcunov Date: Wed, 20 Aug 2008 16:41:45 -0700 Subject: acpi: add checking for NULL early param The early_param handling function could recieve NULL pointer as argument in case if user didn't enter parameter value. So we have to be ready for a such situation and do check for NULL pointer if needed. Signed-off-by: Cyrill Gorcunov Cc: Andi Kleen Signed-off-by: Andrew Morton Signed-off-by: Andi Kleen diff --git a/drivers/acpi/tables.c b/drivers/acpi/tables.c index c341918..775c97a 100644 --- a/drivers/acpi/tables.c +++ b/drivers/acpi/tables.c @@ -300,6 +300,8 @@ int __init acpi_table_init(void) static int __init acpi_parse_apic_instance(char *str) { + if (!str) + return -EINVAL; acpi_apic_instance = simple_strtoul(str, NULL, 0); -- cgit v0.10.2 From 04da11bfcf511544ae19e0a7e5f994b3237752ac Mon Sep 17 00:00:00 2001 From: Artem Bityutskiy Date: Wed, 20 Aug 2008 17:16:34 +0300 Subject: UBIFS: fix zero-length truncations Always allow truncations to zero, even if budgeting thinks there is no space. UBIFS reserves some space for deletions anyway. Otherwise, the following happans: 1. create a file, and write as much as possible there, until ENOSPC 2. truncate the file, which fails with ENOSPC, which is not good. Signed-off-by: Artem Bityutskiy diff --git a/fs/ubifs/dir.c b/fs/ubifs/dir.c index 5c96f1f..2b267c9 100644 --- a/fs/ubifs/dir.c +++ b/fs/ubifs/dir.c @@ -587,7 +587,6 @@ static int ubifs_unlink(struct inode *dir, struct dentry *dentry) if (err) { if (err != -ENOSPC) return err; - err = 0; budgeted = 0; } diff --git a/fs/ubifs/file.c b/fs/ubifs/file.c index 4071d1c..3d698e2 100644 --- a/fs/ubifs/file.c +++ b/fs/ubifs/file.c @@ -793,7 +793,7 @@ static int do_truncation(struct ubifs_info *c, struct inode *inode, int err; struct ubifs_budget_req req; loff_t old_size = inode->i_size, new_size = attr->ia_size; - int offset = new_size & (UBIFS_BLOCK_SIZE - 1); + int offset = new_size & (UBIFS_BLOCK_SIZE - 1), budgeted = 1; struct ubifs_inode *ui = ubifs_inode(inode); dbg_gen("ino %lu, size %lld -> %lld", inode->i_ino, old_size, new_size); @@ -811,8 +811,15 @@ static int do_truncation(struct ubifs_info *c, struct inode *inode, /* A funny way to budget for truncation node */ req.dirtied_ino_d = UBIFS_TRUN_NODE_SZ; err = ubifs_budget_space(c, &req); - if (err) - return err; + if (err) { + /* + * Treat truncations to zero as deletion and always allow them, + * just like we do for '->unlink()'. + */ + if (new_size || err != -ENOSPC) + return err; + budgeted = 0; + } err = vmtruncate(inode, new_size); if (err) @@ -869,7 +876,12 @@ static int do_truncation(struct ubifs_info *c, struct inode *inode, err = ubifs_jnl_truncate(c, inode, old_size, new_size); mutex_unlock(&ui->ui_mutex); out_budg: - ubifs_release_budget(c, &req); + if (budgeted) + ubifs_release_budget(c, &req); + else { + c->nospace = c->nospace_rp = 0; + smp_wmb(); + } return err; } -- cgit v0.10.2 From 2338263e2cb3cd2f77cdc3fcab0312b6c7fc02c3 Mon Sep 17 00:00:00 2001 From: Henrik Rydberg Date: Fri, 22 Aug 2008 16:18:22 -0400 Subject: Input: bcm5974 - add maintainer entry Signed-off-by: Henrik Rydberg Signed-off-by: Dmitry Torokhov diff --git a/MAINTAINERS b/MAINTAINERS index deedc0d..cdedf04 100644 --- a/MAINTAINERS +++ b/MAINTAINERS @@ -413,6 +413,12 @@ L: linux-laptop@vger.kernel.org W: http://www.canb.auug.org.au/~sfr/ S: Supported +APPLE BCM5974 MULTITOUCH DRIVER +P: Henrik Rydberg +M: rydberg@euromail.se +L: linux-input@vger.kernel.org +S: Maintained + APPLE SMC DRIVER P: Nicolas Boichat M: nicolas@boichat.ch -- cgit v0.10.2 From a1068264522cb0a9b863d5357ade844e490bea41 Mon Sep 17 00:00:00 2001 From: Adrian Bunk Date: Fri, 22 Aug 2008 18:20:29 +0300 Subject: sh64: re-add the __strnlen_user() prototype Commit 42fd3b142d8867f5b58d6fb75592cd20fd654c1b (sh: Initial consolidation of the _32/_64 uaccess split.) mistakenly removed the sh64 __strnlen_user() prototype, resulting in the following compile error: <-- snip --> ... CC init/main.o In file included from include/linux/poll.h:13, from include/linux/rtc.h:113, from include/linux/efi.h:19, from init/main.c:43: arch/sh/include/asm/uaccess.h: In function 'strnlen_user': arch/sh/include/asm/uaccess.h:213: error: implicit declaration of function '__strnlen_user' ... make[2]: *** [init/main.o] Error 1 <-- snip --> Reported-by: Adrian Bunk Signed-off-by: Adrian Bunk Signed-off-by: Paul Mundt diff --git a/arch/sh/include/asm/uaccess_64.h b/arch/sh/include/asm/uaccess_64.h index 81b3d51..5580fd4 100644 --- a/arch/sh/include/asm/uaccess_64.h +++ b/arch/sh/include/asm/uaccess_64.h @@ -76,4 +76,6 @@ extern long __put_user_asm_l(void *, long); extern long __put_user_asm_q(void *, long); extern void __put_user_unknown(void); +extern long __strnlen_user(const char *__s, long __n); + #endif /* __ASM_SH_UACCESS_64_H */ -- cgit v0.10.2 From e311be521fa9daedd8959d1a89f5e9bc5b54bb40 Mon Sep 17 00:00:00 2001 From: Adrian Bunk Date: Fri, 22 Aug 2008 18:20:36 +0300 Subject: sh: fix ptrace_64.c:user_disable_single_step() This patch fixes the following compile error caused by commit c459dbf294b4a3d70490a468a7ca3907fb2c2f57 (sh: ptrace single stepping cleanups.): <-- snip --> ... CC arch/sh/kernel/ptrace_64.o arch/sh/kernel/ptrace_64.c: In function 'user_disable_single_step': arch/sh/kernel/ptrace_64.c:134: error: 'regs' undeclared (first use in this function) arch/sh/kernel/ptrace_64.c:134: error: (Each undeclared identifier is reported only once arch/sh/kernel/ptrace_64.c:134: error: for each function it appears in.) ... make[2]: *** [arch/sh/kernel/ptrace_64.o] Error 1 <-- snip --> Reported-by: Adrian Bunk Signed-off-by: Adrian Bunk Signed-off-by: Paul Mundt diff --git a/arch/sh/kernel/ptrace_64.c b/arch/sh/kernel/ptrace_64.c index 5922edd..9c64248 100644 --- a/arch/sh/kernel/ptrace_64.c +++ b/arch/sh/kernel/ptrace_64.c @@ -131,6 +131,8 @@ void user_enable_single_step(struct task_struct *child) void user_disable_single_step(struct task_struct *child) { + struct pt_regs *regs = child->thread.uregs; + regs->sr &= ~SR_SSTEP; } -- cgit v0.10.2 From de82ff783bcb2b52353a7c99b4a8524ae739da73 Mon Sep 17 00:00:00 2001 From: Bjorn Helgaas Date: Fri, 22 Aug 2008 09:47:17 -0600 Subject: PNPACPI: ignore the producer/consumer bit for extended IRQ descriptors The Extended Interrupt descriptor has a producer/consumer bit, but it's not clear what that would mean, and existing BIOSes use the bit inconsistently. This patch makes Linux PNPACPI ignore the bit. The ACPI spec contains examples of PCI Interrupt Link devices marked as ResourceProducers, but many BIOSes mark them as ResourceConsumers. I also checked with a Windows contact, who said: Windows uses only "resource consumer" when dealing with interrupts. There's no useful way of looking at a resource producer of interrupts. ... NT-based Windows largely infers the producer/consumer stuff from the device type and ignores the bits in the namespace. This was necessary because Windows 98 ignored them and early namespaces contained random junk. The reason I want to change this is because if PNPACPI devices exclude ResourceProducer IRQ resources, we can't write PNP drivers for those devices. For example, on machines such as the the HP rx7620, rx7640, rx8620, rx8640, and Superdome, HPET interrupts are ResourceProducers. The HPET driver currently has to use acpi_bus_register_driver() and do its own _CRS parsing, even though it requires absolutely no ACPI-specific functionality. It would be better if the HPET driver were a PNP driver and took advantage of the _CRS parsing built into PNPACPI. This producer/consumer check was originally added here: http://git.kernel.org/?p=linux/kernel/git/torvalds/linux-2.6.git;a=commitdiff;h=2b8de5f50e4a302b83ebcd5b0120621336d50bd6 to fix this bug: http://bugzilla.kernel.org/show_bug.cgi?id=6292 However, the bug was related only to memory and I/O port resources, where the distinction is sensible and important to Linux. Given that the distinction is muddled for IRQ resources, I think it was a mistake to add the check there. Signed-off-by: Bjorn Helgaas Signed-off-by: Andi Kleen diff --git a/drivers/pnp/pnpacpi/rsparser.c b/drivers/pnp/pnpacpi/rsparser.c index d7e9f21..95015cb 100644 --- a/drivers/pnp/pnpacpi/rsparser.c +++ b/drivers/pnp/pnpacpi/rsparser.c @@ -405,8 +405,6 @@ static acpi_status pnpacpi_allocated_resource(struct acpi_resource *res, case ACPI_RESOURCE_TYPE_EXTENDED_IRQ: extended_irq = &res->data.extended_irq; - if (extended_irq->producer_consumer == ACPI_PRODUCER) - return AE_OK; if (extended_irq->interrupt_count == 0) pnp_add_irq_resource(dev, 0, IORESOURCE_DISABLED); -- cgit v0.10.2 From 761e29f3bb19b05bea55285dfdf2d28e001a63b8 Mon Sep 17 00:00:00 2001 From: Adrian Hunter Date: Wed, 20 Aug 2008 16:32:40 +0300 Subject: UBIFS: always read hashed-key nodes under TNC mutex Leaf-nodes that have a hashed key are stored in the leaf-node-cache (LNC) which is protected by the TNC mutex. Consequently, when reading a leaf node with a hashed key (i.e. directory entries, xattr entries) the TNC mutex is always required. Signed-off-by: Adrian Hunter diff --git a/fs/ubifs/tnc.c b/fs/ubifs/tnc.c index e909f4a..4fbc592 100644 --- a/fs/ubifs/tnc.c +++ b/fs/ubifs/tnc.c @@ -1498,7 +1498,6 @@ static int do_lookup_nm(struct ubifs_info *c, const union ubifs_key *key, { int found, n, err; struct ubifs_znode *znode; - struct ubifs_zbranch zbr; dbg_tnc("name '%.*s' key %s", nm->len, nm->name, DBGKEY(key)); mutex_lock(&c->tnc_mutex); @@ -1522,11 +1521,7 @@ static int do_lookup_nm(struct ubifs_info *c, const union ubifs_key *key, goto out_unlock; } - zbr = znode->zbranch[n]; - mutex_unlock(&c->tnc_mutex); - - err = tnc_read_node_nm(c, &zbr, node); - return err; + err = tnc_read_node_nm(c, &znode->zbranch[n], node); out_unlock: mutex_unlock(&c->tnc_mutex); -- cgit v0.10.2 From 601c0bc46753007be011b513ba4fc50ed8e30aef Mon Sep 17 00:00:00 2001 From: Adrian Hunter Date: Fri, 22 Aug 2008 14:23:35 +0300 Subject: UBIFS: allow for racing between GC and TNC The TNC mutex is unlocked prematurely when reading leaf nodes with non-hashed keys. This is unsafe because the node may be moved by garbage collection and the eraseblock unmapped, although that has never actually happened during stress testing. This patch fixes the flaw by detecting the race and retrying with the TNC mutex locked. Signed-off-by: Adrian Hunter diff --git a/fs/ubifs/gc.c b/fs/ubifs/gc.c index d0f3dac..13f1019 100644 --- a/fs/ubifs/gc.c +++ b/fs/ubifs/gc.c @@ -344,6 +344,12 @@ int ubifs_garbage_collect_leb(struct ubifs_info *c, struct ubifs_lprops *lp) if (err) goto out; + /* Allow for races with TNC */ + c->gced_lnum = lnum; + smp_wmb(); + c->gc_seq += 1; + smp_wmb(); + if (c->gc_lnum == -1) { c->gc_lnum = lnum; err = LEB_RETAINED; diff --git a/fs/ubifs/misc.h b/fs/ubifs/misc.h index 87dabf9..87ced4c 100644 --- a/fs/ubifs/misc.h +++ b/fs/ubifs/misc.h @@ -325,4 +325,21 @@ static inline struct timespec ubifs_current_time(struct inode *inode) current_fs_time(inode->i_sb) : CURRENT_TIME_SEC; } +/** + * ubifs_tnc_lookup - look up a file-system node. + * @c: UBIFS file-system description object + * @key: node key to lookup + * @node: the node is returned here + * + * This function look up and reads node with key @key. The caller has to make + * sure the @node buffer is large enough to fit the node. Returns zero in case + * of success, %-ENOENT if the node was not found, and a negative error code in + * case of failure. + */ +static inline int ubifs_tnc_lookup(struct ubifs_info *c, + const union ubifs_key *key, void *node) +{ + return ubifs_tnc_locate(c, key, node, NULL, NULL); +} + #endif /* __UBIFS_MISC_H__ */ diff --git a/fs/ubifs/tnc.c b/fs/ubifs/tnc.c index 4fbc592..7da209a 100644 --- a/fs/ubifs/tnc.c +++ b/fs/ubifs/tnc.c @@ -506,7 +506,7 @@ static int fallible_read_node(struct ubifs_info *c, const union ubifs_key *key, if (keys_cmp(c, key, &node_key) != 0) ret = 0; } - if (ret == 0) + if (ret == 0 && c->replaying) dbg_mnt("dangling branch LEB %d:%d len %d, key %s", zbr->lnum, zbr->offs, zbr->len, DBGKEY(key)); return ret; @@ -1382,50 +1382,39 @@ static int lookup_level0_dirty(struct ubifs_info *c, const union ubifs_key *key, } /** - * ubifs_tnc_lookup - look up a file-system node. + * maybe_leb_gced - determine if a LEB may have been garbage collected. * @c: UBIFS file-system description object - * @key: node key to lookup - * @node: the node is returned here + * @lnum: LEB number + * @gc_seq1: garbage collection sequence number * - * This function look up and reads node with key @key. The caller has to make - * sure the @node buffer is large enough to fit the node. Returns zero in case - * of success, %-ENOENT if the node was not found, and a negative error code in - * case of failure. + * This function determines if @lnum may have been garbage collected since + * sequence number @gc_seq1. If it may have been then %1 is returned, otherwise + * %0 is returned. */ -int ubifs_tnc_lookup(struct ubifs_info *c, const union ubifs_key *key, - void *node) +static int maybe_leb_gced(struct ubifs_info *c, int lnum, int gc_seq1) { - int found, n, err; - struct ubifs_znode *znode; - struct ubifs_zbranch zbr, *zt; - - mutex_lock(&c->tnc_mutex); - found = ubifs_lookup_level0(c, key, &znode, &n); - if (!found) { - err = -ENOENT; - goto out; - } else if (found < 0) { - err = found; - goto out; - } - zt = &znode->zbranch[n]; - if (is_hash_key(c, key)) { - /* - * In this case the leaf node cache gets used, so we pass the - * address of the zbranch and keep the mutex locked - */ - err = tnc_read_node_nm(c, zt, node); - goto out; - } - zbr = znode->zbranch[n]; - mutex_unlock(&c->tnc_mutex); - - err = ubifs_tnc_read_node(c, &zbr, node); - return err; + int gc_seq2, gced_lnum; -out: - mutex_unlock(&c->tnc_mutex); - return err; + gced_lnum = c->gced_lnum; + smp_rmb(); + gc_seq2 = c->gc_seq; + /* Same seq means no GC */ + if (gc_seq1 == gc_seq2) + return 0; + /* Different by more than 1 means we don't know */ + if (gc_seq1 + 1 != gc_seq2) + return 1; + /* + * We have seen the sequence number has increased by 1. Now we need to + * be sure we read the right LEB number, so read it again. + */ + smp_rmb(); + if (gced_lnum != c->gced_lnum) + return 1; + /* Finally we can check lnum */ + if (gced_lnum == lnum) + return 1; + return 0; } /** @@ -1436,16 +1425,19 @@ out: * @lnum: LEB number is returned here * @offs: offset is returned here * - * This function is the same as 'ubifs_tnc_lookup()' but it returns the node - * location also. See 'ubifs_tnc_lookup()'. + * This function look up and reads node with key @key. The caller has to make + * sure the @node buffer is large enough to fit the node. Returns zero in case + * of success, %-ENOENT if the node was not found, and a negative error code in + * case of failure. The node location can be returned in @lnum and @offs. */ int ubifs_tnc_locate(struct ubifs_info *c, const union ubifs_key *key, void *node, int *lnum, int *offs) { - int found, n, err; + int found, n, err, safely = 0, gc_seq1; struct ubifs_znode *znode; struct ubifs_zbranch zbr, *zt; +again: mutex_lock(&c->tnc_mutex); found = ubifs_lookup_level0(c, key, &znode, &n); if (!found) { @@ -1456,24 +1448,43 @@ int ubifs_tnc_locate(struct ubifs_info *c, const union ubifs_key *key, goto out; } zt = &znode->zbranch[n]; + if (lnum) { + *lnum = zt->lnum; + *offs = zt->offs; + } if (is_hash_key(c, key)) { /* * In this case the leaf node cache gets used, so we pass the * address of the zbranch and keep the mutex locked */ - *lnum = zt->lnum; - *offs = zt->offs; err = tnc_read_node_nm(c, zt, node); goto out; } + if (safely) { + err = ubifs_tnc_read_node(c, zt, node); + goto out; + } + /* Drop the TNC mutex prematurely and race with garbage collection */ zbr = znode->zbranch[n]; + gc_seq1 = c->gc_seq; mutex_unlock(&c->tnc_mutex); - *lnum = zbr.lnum; - *offs = zbr.offs; + if (ubifs_get_wbuf(c, zbr.lnum)) { + /* We do not GC journal heads */ + err = ubifs_tnc_read_node(c, &zbr, node); + return err; + } - err = ubifs_tnc_read_node(c, &zbr, node); - return err; + err = fallible_read_node(c, key, &zbr, node); + if (maybe_leb_gced(c, zbr.lnum, gc_seq1)) { + /* + * The node may have been GC'ed out from under us so try again + * while keeping the TNC mutex locked. + */ + safely = 1; + goto again; + } + return 0; out: mutex_unlock(&c->tnc_mutex); diff --git a/fs/ubifs/ubifs.h b/fs/ubifs/ubifs.h index d7f706f..7828d69 100644 --- a/fs/ubifs/ubifs.h +++ b/fs/ubifs/ubifs.h @@ -1028,6 +1028,8 @@ struct ubifs_mount_opts { * @sbuf: a buffer of LEB size used by GC and replay for scanning * @idx_gc: list of index LEBs that have been garbage collected * @idx_gc_cnt: number of elements on the idx_gc list + * @gc_seq: incremented for every non-index LEB garbage collected + * @gced_lnum: last non-index LEB that was garbage collected * * @infos_list: links all 'ubifs_info' objects * @umount_mutex: serializes shrinker and un-mount @@ -1257,6 +1259,8 @@ struct ubifs_info { void *sbuf; struct list_head idx_gc; int idx_gc_cnt; + volatile int gc_seq; + volatile int gced_lnum; struct list_head infos_list; struct mutex umount_mutex; @@ -1451,8 +1455,6 @@ int ubifs_save_dirty_idx_lnums(struct ubifs_info *c); /* tnc.c */ int ubifs_lookup_level0(struct ubifs_info *c, const union ubifs_key *key, struct ubifs_znode **zn, int *n); -int ubifs_tnc_lookup(struct ubifs_info *c, const union ubifs_key *key, - void *node); int ubifs_tnc_lookup_nm(struct ubifs_info *c, const union ubifs_key *key, void *node, const struct qstr *nm); int ubifs_tnc_locate(struct ubifs_info *c, const union ubifs_key *key, -- cgit v0.10.2 From 34894c7843e00972d88b3592027703d4e05a06a7 Mon Sep 17 00:00:00 2001 From: Magnus Damm Date: Wed, 27 Aug 2008 18:15:43 +0900 Subject: sh: crash kernel resource fix The reserved crash kernel memory range is currently missing from /proc/iomem. crashk_res is mistakenly setup after __add_active_range(). Reorder things to make sure the resource shows up in /proc/iomem. Signed-off-by: Magnus Damm Signed-off-by: Paul Mundt diff --git a/arch/sh/kernel/setup.c b/arch/sh/kernel/setup.c index a352076..de83205 100644 --- a/arch/sh/kernel/setup.c +++ b/arch/sh/kernel/setup.c @@ -171,6 +171,7 @@ static void __init reserve_crashkernel(void) (unsigned long)(free_mem >> 20)); crashk_res.start = crash_base; crashk_res.end = crash_base + crash_size - 1; + insert_resource(&iomem_resource, &crashk_res); } } #else @@ -204,11 +205,6 @@ void __init __add_active_range(unsigned int nid, unsigned long start_pfn, request_resource(res, &data_resource); request_resource(res, &bss_resource); -#ifdef CONFIG_KEXEC - if (crashk_res.start != crashk_res.end) - request_resource(res, &crashk_res); -#endif - add_active_range(nid, start_pfn, end_pfn); } -- cgit v0.10.2 From 5734493bac88b28d8d7e2f262305fd6e83545ac5 Mon Sep 17 00:00:00 2001 From: Magnus Damm Date: Wed, 27 Aug 2008 18:19:01 +0900 Subject: sh: fix kexec entry point for crash kernels The crash kernel entry point is currently checked by the kexec kernel code and only physical addresses in the reserved memory window are accepted. This means that we can't pass P2 or P1 addresses as entry points in the case of crash kernels. This patch makes sure we can start crash kernels by adding support for physical address entry points. Signed-off-by: Magnus Damm Signed-off-by: Paul Mundt diff --git a/arch/sh/kernel/machine_kexec.c b/arch/sh/kernel/machine_kexec.c index 4703dff..94df56b 100644 --- a/arch/sh/kernel/machine_kexec.c +++ b/arch/sh/kernel/machine_kexec.c @@ -102,7 +102,7 @@ void machine_kexec(struct kimage *image) /* now call it */ rnk = (relocate_new_kernel_t) reboot_code_buffer; - (*rnk)(page_list, reboot_code_buffer, image->start, vbr_reg); + (*rnk)(page_list, reboot_code_buffer, P2SEGADDR(image->start), vbr_reg); } void arch_crash_save_vmcoreinfo(void) -- cgit v0.10.2 From c773d8af8ebccb723e9843c1e73840b2c5e00572 Mon Sep 17 00:00:00 2001 From: Magnus Damm Date: Wed, 27 Aug 2008 18:21:29 +0900 Subject: sh: fix platform_resource_setup_memory() section mismatch This patch kills a section mismatch for platform_resource_setup_memory(). Signed-off-by: Magnus Damm Signed-off-by: Paul Mundt diff --git a/arch/sh/mm/consistent.c b/arch/sh/mm/consistent.c index 895bb3f..64b8f7f 100644 --- a/arch/sh/mm/consistent.c +++ b/arch/sh/mm/consistent.c @@ -101,7 +101,7 @@ static int __init memchunk_setup(char *str) } __setup("memchunk.", memchunk_setup); -static void memchunk_cmdline_override(char *name, unsigned long *sizep) +static void __init memchunk_cmdline_override(char *name, unsigned long *sizep) { char *p = boot_command_line; int k = strlen(name); @@ -118,8 +118,8 @@ static void memchunk_cmdline_override(char *name, unsigned long *sizep) } } -int platform_resource_setup_memory(struct platform_device *pdev, - char *name, unsigned long memsize) +int __init platform_resource_setup_memory(struct platform_device *pdev, + char *name, unsigned long memsize) { struct resource *r; dma_addr_t dma_handle; -- cgit v0.10.2 From be8c129f1a853daac9085d81256c9d4bd38c6a11 Mon Sep 17 00:00:00 2001 From: Magnus Damm Date: Wed, 27 Aug 2008 18:22:49 +0900 Subject: sh: update Migo-R defconfig This patch updates the MigoR defconfig to include the recently merged uio_pdrv_genirq driver. Signed-off-by: Magnus Damm Signed-off-by: Paul Mundt diff --git a/arch/sh/configs/migor_defconfig b/arch/sh/configs/migor_defconfig index c4b3e1d..4f8b197 100644 --- a/arch/sh/configs/migor_defconfig +++ b/arch/sh/configs/migor_defconfig @@ -1,7 +1,7 @@ # # Automatically generated make config: don't edit -# Linux kernel version: 2.6.26 -# Wed Jul 30 01:44:41 2008 +# Linux kernel version: 2.6.27-rc4 +# Tue Aug 26 14:18:17 2008 # CONFIG_SUPERH=y CONFIG_SUPERH32=y @@ -11,6 +11,7 @@ CONFIG_GENERIC_BUG=y CONFIG_GENERIC_FIND_NEXT_BIT=y CONFIG_GENERIC_HWEIGHT=y CONFIG_GENERIC_HARDIRQS=y +CONFIG_GENERIC_HARDIRQS_NO__DO_IRQ=y CONFIG_GENERIC_IRQ_PROBE=y CONFIG_GENERIC_CALIBRATE_DELAY=y CONFIG_GENERIC_TIME=y @@ -21,7 +22,6 @@ CONFIG_LOCKDEP_SUPPORT=y # CONFIG_ARCH_HAS_ILOG2_U32 is not set # CONFIG_ARCH_HAS_ILOG2_U64 is not set CONFIG_ARCH_NO_VIRT_TO_BUS=y -CONFIG_ARCH_SUPPORTS_AOUT=y CONFIG_DEFCONFIG_LIST="/lib/modules/$UNAME_RELEASE/.config" # @@ -87,6 +87,7 @@ CONFIG_HAVE_OPROFILE=y # CONFIG_USE_GENERIC_SMP_HELPERS is not set CONFIG_HAVE_CLK=y CONFIG_PROC_PAGE_MONITOR=y +CONFIG_HAVE_GENERIC_DMA_COHERENT=y CONFIG_SLABINFO=y CONFIG_RT_MUTEXES=y # CONFIG_TINY_SHMEM is not set @@ -270,6 +271,7 @@ CONFIG_HZ=250 # CONFIG_SCHED_HRTICK is not set # CONFIG_KEXEC is not set # CONFIG_CRASH_DUMP is not set +CONFIG_SECCOMP=y CONFIG_PREEMPT_NONE=y # CONFIG_PREEMPT_VOLUNTARY is not set # CONFIG_PREEMPT is not set @@ -294,10 +296,6 @@ CONFIG_CMDLINE="console=ttySC0,115200 earlyprintk=serial ip=on" # CONFIG_BINFMT_ELF=y # CONFIG_BINFMT_MISC is not set - -# -# Networking -# CONFIG_NET=y # @@ -649,6 +647,7 @@ CONFIG_HW_RANDOM=y CONFIG_I2C=y CONFIG_I2C_BOARDINFO=y # CONFIG_I2C_CHARDEV is not set +CONFIG_I2C_HELPER_AUTO=y # # I2C Hardware Bus support @@ -709,6 +708,7 @@ CONFIG_SSB_POSSIBLE=y # CONFIG_MFD_CORE is not set # CONFIG_MFD_SM501 is not set # CONFIG_HTC_PASIC3 is not set +# CONFIG_MFD_TMIO is not set # # Multimedia devices @@ -755,6 +755,8 @@ CONFIG_USB_ARCH_HAS_HCD=y # CONFIG_USB is not set # CONFIG_USB_OTG_WHITELIST is not set # CONFIG_USB_OTG_BLACKLIST_HUB is not set +# CONFIG_USB_MUSB_HDRC is not set +# CONFIG_USB_GADGET_MUSB_HDRC is not set # # NOTE: USB_STORAGE enables SCSI, and 'SCSI disk support' @@ -842,7 +844,10 @@ CONFIG_RTC_DRV_RS5C372=y # CONFIG_RTC_DRV_SH=y # CONFIG_DMADEVICES is not set -# CONFIG_UIO is not set +CONFIG_UIO=y +# CONFIG_UIO_PDRV is not set +CONFIG_UIO_PDRV_GENIRQ=y +# CONFIG_UIO_SMX is not set # # File systems -- cgit v0.10.2 From f9bed3f2040b2ed44f0d1b7f0280458533c5d2a0 Mon Sep 17 00:00:00 2001 From: Magnus Damm Date: Wed, 27 Aug 2008 18:23:52 +0900 Subject: sh: update AP325RXA defconfig This patch updates the AP325RXA defconfig to include the recently merged uio_pdrv_genirq driver. Signed-off-by: Magnus Damm Signed-off-by: Paul Mundt diff --git a/arch/sh/configs/ap325rxa_defconfig b/arch/sh/configs/ap325rxa_defconfig index 29926a9..851c870 100644 --- a/arch/sh/configs/ap325rxa_defconfig +++ b/arch/sh/configs/ap325rxa_defconfig @@ -1,7 +1,7 @@ # # Automatically generated make config: don't edit -# Linux kernel version: 2.6.26 -# Wed Jul 30 01:18:59 2008 +# Linux kernel version: 2.6.27-rc4 +# Tue Aug 26 14:21:17 2008 # CONFIG_SUPERH=y CONFIG_SUPERH32=y @@ -11,6 +11,7 @@ CONFIG_GENERIC_BUG=y CONFIG_GENERIC_FIND_NEXT_BIT=y CONFIG_GENERIC_HWEIGHT=y CONFIG_GENERIC_HARDIRQS=y +CONFIG_GENERIC_HARDIRQS_NO__DO_IRQ=y CONFIG_GENERIC_IRQ_PROBE=y CONFIG_GENERIC_CALIBRATE_DELAY=y CONFIG_GENERIC_TIME=y @@ -20,7 +21,6 @@ CONFIG_LOCKDEP_SUPPORT=y # CONFIG_ARCH_HAS_ILOG2_U32 is not set # CONFIG_ARCH_HAS_ILOG2_U64 is not set CONFIG_ARCH_NO_VIRT_TO_BUS=y -CONFIG_ARCH_SUPPORTS_AOUT=y CONFIG_DEFCONFIG_LIST="/lib/modules/$UNAME_RELEASE/.config" # @@ -58,7 +58,6 @@ CONFIG_SYSCTL=y CONFIG_EMBEDDED=y CONFIG_UID16=y CONFIG_SYSCTL_SYSCALL=y -CONFIG_SYSCTL_SYSCALL_CHECK=y # CONFIG_KALLSYMS is not set CONFIG_HOTPLUG=y CONFIG_PRINTK=y @@ -89,6 +88,7 @@ CONFIG_HAVE_OPROFILE=y # CONFIG_USE_GENERIC_SMP_HELPERS is not set CONFIG_HAVE_CLK=y CONFIG_PROC_PAGE_MONITOR=y +CONFIG_HAVE_GENERIC_DMA_COHERENT=y CONFIG_SLABINFO=y CONFIG_RT_MUTEXES=y # CONFIG_TINY_SHMEM is not set @@ -261,9 +261,10 @@ CONFIG_HZ_250=y # CONFIG_HZ_300 is not set # CONFIG_HZ_1000 is not set CONFIG_HZ=250 -# CONFIG_SCHED_HRTICK is not set +CONFIG_SCHED_HRTICK=y # CONFIG_KEXEC is not set # CONFIG_CRASH_DUMP is not set +CONFIG_SECCOMP=y # CONFIG_PREEMPT_NONE is not set # CONFIG_PREEMPT_VOLUNTARY is not set CONFIG_PREEMPT=y @@ -289,10 +290,6 @@ CONFIG_CMDLINE="console=tty1 console=ttySC5,38400 root=/dev/nfs ip=dhcp" # CONFIG_BINFMT_ELF=y # CONFIG_BINFMT_MISC is not set - -# -# Networking -# CONFIG_NET=y # @@ -647,6 +644,7 @@ CONFIG_SSB_POSSIBLE=y # CONFIG_MFD_CORE is not set # CONFIG_MFD_SM501 is not set # CONFIG_HTC_PASIC3 is not set +# CONFIG_MFD_TMIO is not set # # Multimedia devices @@ -690,7 +688,10 @@ CONFIG_DUMMY_CONSOLE=y # CONFIG_ACCESSIBILITY is not set # CONFIG_RTC_CLASS is not set # CONFIG_DMADEVICES is not set -# CONFIG_UIO is not set +CONFIG_UIO=y +# CONFIG_UIO_PDRV is not set +CONFIG_UIO_PDRV_GENIRQ=y +# CONFIG_UIO_SMX is not set # # File systems @@ -854,6 +855,7 @@ CONFIG_FRAME_WARN=1024 # CONFIG_DEBUG_KERNEL is not set # CONFIG_DEBUG_BUGVERBOSE is not set # CONFIG_DEBUG_MEMORY_INIT is not set +CONFIG_SYSCTL_SYSCALL_CHECK=y # CONFIG_SAMPLES is not set # CONFIG_SH_STANDARD_BIOS is not set # CONFIG_EARLY_SCIF_CONSOLE is not set -- cgit v0.10.2 From 3c31bf73134038a417a9ae3fa3c02c279b42c550 Mon Sep 17 00:00:00 2001 From: Yoshihiro Shimoda Date: Wed, 27 Aug 2008 20:16:46 +0900 Subject: sh: fix semtimedop syscall fix the problem that cannot work semtimedop system call. Signed-off-by: Yoshihiro Shimoda Signed-off-by: Paul Mundt diff --git a/arch/sh/kernel/sys_sh.c b/arch/sh/kernel/sys_sh.c index 59cd285..9061b86 100644 --- a/arch/sh/kernel/sys_sh.c +++ b/arch/sh/kernel/sys_sh.c @@ -170,7 +170,7 @@ asmlinkage int sys_ipc(uint call, int first, int second, version = call >> 16; /* hack for backward compatibility */ call &= 0xffff; - if (call <= SEMCTL) + if (call <= SEMTIMEDOP) switch (call) { case SEMOP: return sys_semtimedop(first, -- cgit v0.10.2 From 9662e0802445a1f56cef11bbd0d520b07238424a Mon Sep 17 00:00:00 2001 From: Jeremy Fitzhardinge Date: Wed, 27 Aug 2008 21:04:49 -0700 Subject: ACPI: thinkpad-acpi: wan radio control is not experimental The WWAN radio control has been working well for over three years, and is no longer experimental. Signed-off-by: Jeremy Fitzhardinge Signed-off-by: Andi Kleen diff --git a/Documentation/laptops/thinkpad-acpi.txt b/Documentation/laptops/thinkpad-acpi.txt index 02dc748..71f0fe1 100644 --- a/Documentation/laptops/thinkpad-acpi.txt +++ b/Documentation/laptops/thinkpad-acpi.txt @@ -44,7 +44,7 @@ detailed description): - LCD brightness control - Volume control - Fan control and monitoring: fan speed, fan enable/disable - - Experimental: WAN enable and disable + - WAN enable and disable A compatibility table by model and feature is maintained on the web site, http://ibm-acpi.sf.net/. I appreciate any success or failure @@ -1375,18 +1375,13 @@ with EINVAL, try to set pwm1_enable to 1 and pwm1 to at least 128 (255 would be the safest choice, though). -EXPERIMENTAL: WAN ------------------ +WAN +--- procfs: /proc/acpi/ibm/wan sysfs device attribute: wwan_enable (deprecated) sysfs rfkill class: switch "tpacpi_wwan_sw" -This feature is marked EXPERIMENTAL because the implementation -directly accesses hardware registers and may not work as expected. USE -WITH CAUTION! To use this feature, you need to supply the -experimental=1 parameter when loading the module. - This feature shows the presence and current state of a W-WAN (Sierra Wireless EV-DO) device. diff --git a/drivers/misc/thinkpad_acpi.c b/drivers/misc/thinkpad_acpi.c index d3eb790..6b93007 100644 --- a/drivers/misc/thinkpad_acpi.c +++ b/drivers/misc/thinkpad_acpi.c @@ -3086,7 +3086,6 @@ static struct ibm_struct wan_driver_data = { .read = wan_read, .write = wan_write, .exit = wan_exit, - .flags.experimental = 1, }; /************************************************************************* -- cgit v0.10.2 From 8191e1fa8131a422f4bf7b0f2dc1f8543fd17783 Mon Sep 17 00:00:00 2001 From: Artem Bityutskiy Date: Fri, 22 Aug 2008 12:26:40 +0300 Subject: UBIFS: do not update min_idx_lebs in stafs This is bad because the rest of the code should not depend on it, and this may hide bugss, instead of revealing them. Signed-off-by: Artem Bityutskiy diff --git a/fs/ubifs/budget.c b/fs/ubifs/budget.c index 15409815..ac0d2e1 100644 --- a/fs/ubifs/budget.c +++ b/fs/ubifs/budget.c @@ -741,7 +741,6 @@ long long ubifs_budg_get_free_space(struct ubifs_info *c) available = ubifs_calc_available(c, min_idx_lebs); outstanding = c->budg_data_growth + c->budg_dd_growth; - c->min_idx_lebs = min_idx_lebs; spin_unlock(&c->space_lock); if (available > outstanding) -- cgit v0.10.2 From 9e5de3549615818cae9c20a0ee1fd3ad4a747758 Mon Sep 17 00:00:00 2001 From: Artem Bityutskiy Date: Mon, 25 Aug 2008 17:29:43 +0300 Subject: UBIFS: push empty flash hack down We have a hack which forces the amount of flash space to be equivalent to 'c->blocks_cnt' in case of empty FS. This is to make users happy and see '%0' used in 'df' when they mount an empty FS. This hack is not needed in 'ubifs_calc_available()', but it is only needed the caller, in 'ubifs_budg_get_free_space()'. So push it down there. Signed-off-by: Artem Bityutskiy diff --git a/fs/ubifs/budget.c b/fs/ubifs/budget.c index ac0d2e1..f6d2eaa 100644 --- a/fs/ubifs/budget.c +++ b/fs/ubifs/budget.c @@ -302,18 +302,6 @@ long long ubifs_calc_available(const struct ubifs_info *c, int min_idx_lebs) int subtract_lebs; long long available; - /* - * Force the amount available to the total size reported if the used - * space is zero. - */ - if (c->lst.total_used <= UBIFS_INO_NODE_SZ && - c->budg_data_growth + c->budg_dd_growth == 0) { - /* Do the same calculation as for c->block_cnt */ - available = c->main_lebs - 2; - available *= c->leb_size - c->dark_wm; - return available; - } - available = c->main_bytes - c->lst.total_used; /* @@ -739,8 +727,18 @@ long long ubifs_budg_get_free_space(struct ubifs_info *c) return 0; } - available = ubifs_calc_available(c, min_idx_lebs); outstanding = c->budg_data_growth + c->budg_dd_growth; + + /* + * Force the amount available to the total size reported if the used + * space is zero. + */ + if (c->lst.total_used <= UBIFS_INO_NODE_SZ && !outstanding) { + spin_unlock(&c->space_lock); + return (long long)c->block_cnt << UBIFS_BLOCK_SHIFT; + } + + available = ubifs_calc_available(c, min_idx_lebs); spin_unlock(&c->space_lock); if (available > outstanding) diff --git a/fs/ubifs/super.c b/fs/ubifs/super.c index f71e6b8..1018053 100644 --- a/fs/ubifs/super.c +++ b/fs/ubifs/super.c @@ -649,8 +649,6 @@ static int init_constants_late(struct ubifs_info *c) * * Subtract the LEB reserved for GC and the LEB which is reserved for * deletions. - * - * Review 'ubifs_calc_available()' if changing this calculation. */ tmp64 = c->main_lebs - 2; tmp64 *= (uint64_t)c->leb_size - c->dark_wm; -- cgit v0.10.2 From 8aabb75017291ba68c09ff5fdb998ef0a1fdaaf9 Mon Sep 17 00:00:00 2001 From: Artem Bityutskiy Date: Mon, 25 Aug 2008 16:02:31 +0300 Subject: UBIFS: remove incorrect index space check When we report free space to user-space, we should not report 0 if the amount of empty LEBs is too low, because they would be produced by GC when needed. Thus, just call 'ubifs_calc_available()' straight away which would take 'min_idx_lebs' into account anyway. Signed-off-by: Artem Bityutskiy diff --git a/fs/ubifs/budget.c b/fs/ubifs/budget.c index f6d2eaa..9ef630a 100644 --- a/fs/ubifs/budget.c +++ b/fs/ubifs/budget.c @@ -709,24 +709,11 @@ void ubifs_release_dirty_inode_budget(struct ubifs_info *c, */ long long ubifs_budg_get_free_space(struct ubifs_info *c) { - int min_idx_lebs, rsvd_idx_lebs; + int min_idx_lebs; long long available, outstanding, free; - /* Do exactly the same calculations as in 'do_budget_space()' */ spin_lock(&c->space_lock); min_idx_lebs = ubifs_calc_min_idx_lebs(c); - - if (min_idx_lebs > c->lst.idx_lebs) - rsvd_idx_lebs = min_idx_lebs - c->lst.idx_lebs; - else - rsvd_idx_lebs = 0; - - if (rsvd_idx_lebs > c->lst.empty_lebs + c->freeable_cnt + c->idx_gc_cnt - - c->lst.taken_empty_lebs) { - spin_unlock(&c->space_lock); - return 0; - } - outstanding = c->budg_data_growth + c->budg_dd_growth; /* -- cgit v0.10.2 From 4b5f2762ec914c9dfd0e9d2377c0574f2ee9a8f9 Mon Sep 17 00:00:00 2001 From: Artem Bityutskiy Date: Mon, 25 Aug 2008 16:15:56 +0300 Subject: UBIFS: improve statfs reporting Make free space calculation less pessimistic and more realistic, which in turn improves 'statfs()' reports. Now it lies by 10%-20%, instead of 20%-30% (10% more honest). Results of "freespace" test (120MiB volume, 16KiB LEB size, 512 bytes page size). Before the change: freespace: Test 1: fill the space we have 3 times freespace: was free: 78274560 bytes 74.6 MiB, wrote: 96489472 bytes 92.0 MiB, delta: 18214912 bytes 17.4 MiB, wrote 23.3% more than predicted freespace: was free: 76754944 bytes 73.2 MiB, wrote: 96493568 bytes 92.0 MiB, delta: 19738624 bytes 18.8 MiB, wrote 25.7% more than predicted freespace: was free: 76759040 bytes 73.2 MiB, wrote: 96489472 bytes 92.0 MiB, delta: 19730432 bytes 18.8 MiB, wrote 25.7% more than predicted freespace: Test 1 finished freespace: Test 2: gradually lessen amount of free space and fill the FS freespace: do 10 steps, lessen free space by 6977722 bytes 6.7 MiB each time freespace: was free: 72273920 bytes 68.9 MiB, wrote: 88891392 bytes 84.8 MiB, delta: 16617472 bytes 15.8 MiB, wrote 23.0% more than predicted freespace: was free: 66154496 bytes 63.1 MiB, wrote: 81506304 bytes 77.7 MiB, delta: 15351808 bytes 14.6 MiB, wrote 23.2% more than predicted freespace: was free: 58732544 bytes 56.0 MiB, wrote: 72572928 bytes 69.2 MiB, delta: 13840384 bytes 13.2 MiB, wrote 23.6% more than predicted freespace: was free: 51552256 bytes 49.2 MiB, wrote: 63754240 bytes 60.8 MiB, delta: 12201984 bytes 11.6 MiB, wrote 23.7% more than predicted freespace: was free: 44404736 bytes 42.3 MiB, wrote: 54943744 bytes 52.4 MiB, delta: 10539008 bytes 10.1 MiB, wrote 23.7% more than predicted freespace: was free: 37285888 bytes 35.6 MiB, wrote: 46161920 bytes 44.0 MiB, delta: 8876032 bytes 8.5 MiB, wrote 23.8% more than predicted freespace: was free: 30171136 bytes 28.8 MiB, wrote: 37384192 bytes 35.7 MiB, delta: 7213056 bytes 6.9 MiB, wrote 23.9% more than predicted freespace: was free: 23048192 bytes 22.0 MiB, wrote: 28606464 bytes 27.3 MiB, delta: 5558272 bytes 5.3 MiB, wrote 24.1% more than predicted freespace: was free: 15941632 bytes 15.2 MiB, wrote: 19828736 bytes 18.9 MiB, delta: 3887104 bytes 3.7 MiB, wrote 24.4% more than predicted freespace: was free: 8830976 bytes 8.4 MiB, wrote: 11063296 bytes 10.6 MiB, delta: 2232320 bytes 2.1 MiB, wrote 25.3% more than predicted freespace: Test 2 finished freespace: Test 3: gradually lessen amount of free space by trashing and fill the FS freespace: do 10 steps, lessen free space by 6985541 bytes 6.7 MiB each time freespace: trashing: was free: 76840960 bytes 73.3 MiB, need free: 6985550 bytes 6.7 MiB, files created: 248311, delete 225737 (90.9% of them) freespace: was free: 65228800 bytes 62.2 MiB, wrote: 82530304 bytes 78.7 MiB, delta: 17301504 bytes 16.5 MiB, wrote 26.5% more than predicted freespace: trashing: was free: 74485760 bytes 71.0 MiB, need free: 13971091 bytes 13.3 MiB, files created: 248712, delete 202061 (81.2% of them) freespace: was free: 55025664 bytes 52.5 MiB, wrote: 71925760 bytes 68.6 MiB, delta: 16900096 bytes 16.1 MiB, wrote 30.7% more than predicted freespace: trashing: was free: 75550720 bytes 72.1 MiB, need free: 20956632 bytes 20.0 MiB, files created: 248849, delete 179822 (72.3% of them) freespace: was free: 46669824 bytes 44.5 MiB, wrote: 63197184 bytes 60.3 MiB, delta: 16527360 bytes 15.8 MiB, wrote 35.4% more than predicted freespace: trashing: was free: 76214272 bytes 72.7 MiB, need free: 27942173 bytes 26.6 MiB, files created: 248789, delete 157576 (63.3% of them) freespace: was free: 39129088 bytes 37.3 MiB, wrote: 55164928 bytes 52.6 MiB, delta: 16035840 bytes 15.3 MiB, wrote 41.0% more than predicted freespace: trashing: was free: 77398016 bytes 73.8 MiB, need free: 34927714 bytes 33.3 MiB, files created: 248711, delete 136474 (54.9% of them) freespace: was free: 32325632 bytes 30.8 MiB, wrote: 48234496 bytes 46.0 MiB, delta: 15908864 bytes 15.2 MiB, wrote 49.2% more than predicted freespace: trashing: was free: 75796480 bytes 72.3 MiB, need free: 41913255 bytes 40.0 MiB, files created: 248674, delete 111164 (44.7% of them) freespace: was free: 25079808 bytes 23.9 MiB, wrote: 40775680 bytes 38.9 MiB, delta: 15695872 bytes 15.0 MiB, wrote 62.6% more than predicted freespace: trashing: was free: 78209024 bytes 74.6 MiB, need free: 48898796 bytes 46.6 MiB, files created: 248708, delete 93207 (37.5% of them) freespace: was free: 20582400 bytes 19.6 MiB, wrote: 34844672 bytes 33.2 MiB, delta: 14262272 bytes 13.6 MiB, wrote 69.3% more than predicted freespace: trashing: was free: 77328384 bytes 73.7 MiB, need free: 55884337 bytes 53.3 MiB, files created: 248644, delete 68951 (27.7% of them) freespace: was free: 14368768 bytes 13.7 MiB, wrote: 28278784 bytes 27.0 MiB, delta: 13910016 bytes 13.3 MiB, wrote 96.8% more than predicted freespace: trashing: was free: 77434880 bytes 73.8 MiB, need free: 62869878 bytes 60.0 MiB, files created: 248640, delete 46767 (18.8% of them) freespace: was free: 8286208 bytes 7.9 MiB, wrote: 21811200 bytes 20.8 MiB, delta: 13524992 bytes 12.9 MiB, wrote 163.2% more than predicted freespace: trashing: was free: 77856768 bytes 74.2 MiB, need free: 69855419 bytes 66.6 MiB, files created: 248576, delete 25546 (10.3% of them) freespace: was free: 5570560 bytes 5.3 MiB, wrote: 8187904 bytes 7.8 MiB, delta: 2617344 bytes 2.5 MiB, wrote 47.0% more than predicted freespace: Test 3 finished freespace: finished successfully After the change: freespace: Test 1: fill the space we have 3 times freespace: was free: 85204992 bytes 81.3 MiB, wrote: 96489472 bytes 92.0 MiB, delta: 11284480 bytes 10.8 MiB, wrote 13.2% more than predicted freespace: was free: 83554304 bytes 79.7 MiB, wrote: 96489472 bytes 92.0 MiB, delta: 12935168 bytes 12.3 MiB, wrote 15.5% more than predicted freespace: was free: 83554304 bytes 79.7 MiB, wrote: 96493568 bytes 92.0 MiB, delta: 12939264 bytes 12.3 MiB, wrote 15.5% more than predicted freespace: Test 1 finished freespace: Test 2: gradually lessen amount of free space and fill the FS freespace: do 10 steps, lessen free space by 7596218 bytes 7.2 MiB each time freespace: was free: 78675968 bytes 75.0 MiB, wrote: 88903680 bytes 84.8 MiB, delta: 10227712 bytes 9.8 MiB, wrote 13.0% more than predicted freespace: was free: 72015872 bytes 68.7 MiB, wrote: 81514496 bytes 77.7 MiB, delta: 9498624 bytes 9.1 MiB, wrote 13.2% more than predicted freespace: was free: 63938560 bytes 61.0 MiB, wrote: 72589312 bytes 69.2 MiB, delta: 8650752 bytes 8.2 MiB, wrote 13.5% more than predicted freespace: was free: 56127488 bytes 53.5 MiB, wrote: 63762432 bytes 60.8 MiB, delta: 7634944 bytes 7.3 MiB, wrote 13.6% more than predicted freespace: was free: 48336896 bytes 46.1 MiB, wrote: 54935552 bytes 52.4 MiB, delta: 6598656 bytes 6.3 MiB, wrote 13.7% more than predicted freespace: was free: 40587264 bytes 38.7 MiB, wrote: 46157824 bytes 44.0 MiB, delta: 5570560 bytes 5.3 MiB, wrote 13.7% more than predicted freespace: was free: 32841728 bytes 31.3 MiB, wrote: 37384192 bytes 35.7 MiB, delta: 4542464 bytes 4.3 MiB, wrote 13.8% more than predicted freespace: was free: 25100288 bytes 23.9 MiB, wrote: 28618752 bytes 27.3 MiB, delta: 3518464 bytes 3.4 MiB, wrote 14.0% more than predicted freespace: was free: 17342464 bytes 16.5 MiB, wrote: 19841024 bytes 18.9 MiB, delta: 2498560 bytes 2.4 MiB, wrote 14.4% more than predicted freespace: was free: 9605120 bytes 9.2 MiB, wrote: 11063296 bytes 10.6 MiB, delta: 1458176 bytes 1.4 MiB, wrote 15.2% more than predicted freespace: Test 2 finished freespace: Test 3: gradually lessen amount of free space by trashing and fill the FS freespace: do 10 steps, lessen free space by 7606272 bytes 7.3 MiB each time freespace: trashing: was free: 83668992 bytes 79.8 MiB, need free: 7606272 bytes 7.3 MiB, files created: 248297, delete 225724 (90.9% of them) freespace: was free: 70803456 bytes 67.5 MiB, wrote: 82485248 bytes 78.7 MiB, delta: 11681792 bytes 11.1 MiB, wrote 16.5% more than predicted freespace: trashing: was free: 81080320 bytes 77.3 MiB, need free: 15212544 bytes 14.5 MiB, files created: 248711, delete 202047 (81.2% of them) freespace: was free: 59867136 bytes 57.1 MiB, wrote: 71897088 bytes 68.6 MiB, delta: 12029952 bytes 11.5 MiB, wrote 20.1% more than predicted freespace: trashing: was free: 82243584 bytes 78.4 MiB, need free: 22818816 bytes 21.8 MiB, files created: 248866, delete 179817 (72.3% of them) freespace: was free: 50905088 bytes 48.5 MiB, wrote: 63168512 bytes 60.2 MiB, delta: 12263424 bytes 11.7 MiB, wrote 24.1% more than predicted freespace: trashing: was free: 83402752 bytes 79.5 MiB, need free: 30425088 bytes 29.0 MiB, files created: 248920, delete 158114 (63.5% of them) freespace: was free: 42651648 bytes 40.7 MiB, wrote: 55406592 bytes 52.8 MiB, delta: 12754944 bytes 12.2 MiB, wrote 29.9% more than predicted freespace: trashing: was free: 84402176 bytes 80.5 MiB, need free: 38031360 bytes 36.3 MiB, files created: 248709, delete 136641 (54.9% of them) freespace: was free: 35233792 bytes 33.6 MiB, wrote: 48250880 bytes 46.0 MiB, delta: 13017088 bytes 12.4 MiB, wrote 36.9% more than predicted freespace: trashing: was free: 82530304 bytes 78.7 MiB, need free: 45637632 bytes 43.5 MiB, files created: 248778, delete 111208 (44.7% of them) freespace: was free: 27287552 bytes 26.0 MiB, wrote: 40267776 bytes 38.4 MiB, delta: 12980224 bytes 12.4 MiB, wrote 47.6% more than predicted freespace: trashing: was free: 85114880 bytes 81.2 MiB, need free: 53243904 bytes 50.8 MiB, files created: 248508, delete 93052 (37.4% of them) freespace: was free: 22437888 bytes 21.4 MiB, wrote: 35328000 bytes 33.7 MiB, delta: 12890112 bytes 12.3 MiB, wrote 57.4% more than predicted freespace: trashing: was free: 84103168 bytes 80.2 MiB, need free: 60850176 bytes 58.0 MiB, files created: 248637, delete 68743 (27.6% of them) freespace: was free: 15536128 bytes 14.8 MiB, wrote: 28319744 bytes 27.0 MiB, delta: 12783616 bytes 12.2 MiB, wrote 82.3% more than predicted freespace: trashing: was free: 84357120 bytes 80.4 MiB, need free: 68456448 bytes 65.3 MiB, files created: 248567, delete 46852 (18.8% of them) freespace: was free: 9015296 bytes 8.6 MiB, wrote: 22044672 bytes 21.0 MiB, delta: 13029376 bytes 12.4 MiB, wrote 144.5% more than predicted freespace: trashing: was free: 84942848 bytes 81.0 MiB, need free: 76062720 bytes 72.5 MiB, files created: 248636, delete 25993 (10.5% of them) freespace: was free: 6086656 bytes 5.8 MiB, wrote: 8331264 bytes 7.9 MiB, delta: 2244608 bytes 2.1 MiB, wrote 36.9% more than predicted freespace: Test 3 finished freespace: finished successfully Signed-off-by: Artem Bityutskiy diff --git a/fs/ubifs/budget.c b/fs/ubifs/budget.c index 9ef630a..7851480 100644 --- a/fs/ubifs/budget.c +++ b/fs/ubifs/budget.c @@ -702,6 +702,51 @@ void ubifs_release_dirty_inode_budget(struct ubifs_info *c, } /** + * ubifs_reported_space - calculate reported free space. + * @c: the UBIFS file-system description object + * @free: amount of free space + * + * This function calculates amount of free space which will be reported to + * user-space. User-space application tend to expect that if the file-system + * (e.g., via the 'statfs()' call) reports that it has N bytes available, they + * are able to write a file of size N. UBIFS attaches node headers to each data + * node and it has to write indexind nodes as well. This introduces additional + * overhead, and UBIFS it has to report sligtly less free space to meet the + * above expectetion. + * + * This function assumes free space is made up of uncompressed data nodes and + * full index nodes (one per data node, tripled because we always allow enough + * space to write the index thrice). + * + * Note, the calculation is pessimistic, which means that most of the time + * UBIFS reports less space than it actually has. + */ +long long ubifs_reported_space(const struct ubifs_info *c, uint64_t free) +{ + int divisor, factor; + + /* + * Reported space size is @free * X, where X is UBIFS block size + * divided by UBIFS block size + all overhead one data block + * introduces. The overhead is the node header + indexing overhead. + * + * Indexing overhead is calculations are based on the following + * formula: I = N/(f - 1) + 1, where I - number of indexing nodes, N - + * number of data nodes, f - fanout. Because effective UBIFS fanout is + * twice as less than maximum fanout, we assume that each data node + * introduces 3 * @c->max_idx_node_sz / (@c->fanout/2 - 1) bytes. + * Note, the multiplier 3 is because UBIFS reseves thrice as more space + * for the index. + */ + factor = UBIFS_BLOCK_SIZE; + divisor = UBIFS_MAX_DATA_NODE_SZ; + divisor += (c->max_idx_node_sz * 3) / ((c->fanout >> 1) - 1); + free *= factor; + do_div(free, divisor); + return free; +} + +/** * ubifs_budg_get_free_space - return amount of free space. * @c: UBIFS file-system description object * diff --git a/fs/ubifs/misc.h b/fs/ubifs/misc.h index 87ced4c..4c12a92 100644 --- a/fs/ubifs/misc.h +++ b/fs/ubifs/misc.h @@ -284,38 +284,6 @@ static inline void *ubifs_idx_key(const struct ubifs_info *c, } /** - * ubifs_reported_space - calculate reported free space. - * @c: the UBIFS file-system description object - * @free: amount of free space - * - * This function calculates amount of free space which will be reported to - * user-space. User-space application tend to expect that if the file-system - * (e.g., via the 'statfs()' call) reports that it has N bytes available, they - * are able to write a file of size N. UBIFS attaches node headers to each data - * node and it has to write indexind nodes as well. This introduces additional - * overhead, and UBIFS it has to report sligtly less free space to meet the - * above expectetion. - * - * This function assumes free space is made up of uncompressed data nodes and - * full index nodes (one per data node, doubled because we always allow enough - * space to write the index twice). - * - * Note, the calculation is pessimistic, which means that most of the time - * UBIFS reports less space than it actually has. - */ -static inline long long ubifs_reported_space(const struct ubifs_info *c, - uint64_t free) -{ - int divisor, factor; - - divisor = UBIFS_MAX_DATA_NODE_SZ + (c->max_idx_node_sz * 3); - factor = UBIFS_MAX_DATA_NODE_SZ - UBIFS_DATA_NODE_SZ; - do_div(free, divisor); - - return free * factor; -} - -/** * ubifs_current_time - round current time to time granularity. * @inode: inode */ diff --git a/fs/ubifs/ubifs.h b/fs/ubifs/ubifs.h index 7828d69..681d46e 100644 --- a/fs/ubifs/ubifs.h +++ b/fs/ubifs/ubifs.h @@ -1441,6 +1441,7 @@ void ubifs_cancel_ino_op(struct ubifs_info *c, struct inode *inode, long long ubifs_budg_get_free_space(struct ubifs_info *c); int ubifs_calc_min_idx_lebs(struct ubifs_info *c); void ubifs_convert_page_budget(struct ubifs_info *c); +long long ubifs_reported_space(const struct ubifs_info *c, uint64_t free); long long ubifs_calc_available(const struct ubifs_info *c, int min_idx_lebs); /* find.c */ -- cgit v0.10.2 From ad507653a39e0d27404291e5d813683265388a20 Mon Sep 17 00:00:00 2001 From: Artem Bityutskiy Date: Mon, 25 Aug 2008 18:32:57 +0300 Subject: UBIFS: fix assertion The assertion was incorrect, because it did not take into account free space. This patch also amends the comments correspondingly, and cleans them up a little. Signed-off-by: Artem Bityutskiy diff --git a/fs/ubifs/find.c b/fs/ubifs/find.c index adee7b5..9fc55ae 100644 --- a/fs/ubifs/find.c +++ b/fs/ubifs/find.c @@ -211,14 +211,8 @@ static const struct ubifs_lprops *scan_for_dirty(struct ubifs_info *c, * dirty index heap, and it falls-back to LPT scanning if the heaps are empty * or do not have an LEB which satisfies the @min_space criteria. * - * Note: - * o LEBs which have less than dead watermark of dirty space are never picked - * by this function; - * - * Returns zero and the LEB properties of - * found dirty LEB in case of success, %-ENOSPC if no dirty LEB was found and a - * negative error code in case of other failures. The returned LEB is marked as - * "taken". + * Note, LEBs which have less than dead watermark of free + dirty space are + * never picked by this function. * * The additional @pick_free argument controls if this function has to return a * free or freeable LEB if one is present. For example, GC must to set it to %1, @@ -231,6 +225,10 @@ static const struct ubifs_lprops *scan_for_dirty(struct ubifs_info *c, * * In addition @pick_free is set to %2 by the recovery process in order to * recover gc_lnum in which case an index LEB must not be returned. + * + * This function returns zero and the LEB properties of found dirty LEB in case + * of success, %-ENOSPC if no dirty LEB was found and a negative error code in + * case of other failures. The returned LEB is marked as "taken". */ int ubifs_find_dirty_leb(struct ubifs_info *c, struct ubifs_lprops *ret_lp, int min_space, int pick_free) @@ -317,7 +315,7 @@ int ubifs_find_dirty_leb(struct ubifs_info *c, struct ubifs_lprops *ret_lp, lp = idx_lp; if (lp) { - ubifs_assert(lp->dirty >= c->dead_wm); + ubifs_assert(lp->free + lp->dirty >= c->dead_wm); goto found; } -- cgit v0.10.2 From 131130b9a1e6e523c64b34137b14f88ae1382a6a Mon Sep 17 00:00:00 2001 From: Artem Bityutskiy Date: Mon, 25 Aug 2008 18:34:45 +0300 Subject: UBIFS: add forgotten gc_idx_lebs component We add this component at other similar places, but not in this one. Signed-off-by: Artem Bityutskiy diff --git a/fs/ubifs/find.c b/fs/ubifs/find.c index 9fc55ae..e045c8b 100644 --- a/fs/ubifs/find.c +++ b/fs/ubifs/find.c @@ -243,7 +243,7 @@ int ubifs_find_dirty_leb(struct ubifs_info *c, struct ubifs_lprops *ret_lp, int lebs, rsvd_idx_lebs = 0; spin_lock(&c->space_lock); - lebs = c->lst.empty_lebs; + lebs = c->lst.empty_lebs + c->idx_gc_cnt; lebs += c->freeable_cnt - c->lst.taken_empty_lebs; /* -- cgit v0.10.2 From 9bbb5726efb64e2cfed42f6eec07db80cd87e63b Mon Sep 17 00:00:00 2001 From: Artem Bityutskiy Date: Fri, 22 Aug 2008 18:23:22 +0300 Subject: UBIFS: introduce LEB overhead This is a preparational patch for the following statfs() report fix. Signed-off-by: Artem Bityutskiy diff --git a/fs/ubifs/super.c b/fs/ubifs/super.c index 1018053..be23fd3 100644 --- a/fs/ubifs/super.c +++ b/fs/ubifs/super.c @@ -530,6 +530,12 @@ static int init_constants_early(struct ubifs_info *c) c->dead_wm = ALIGN(MIN_WRITE_SZ, c->min_io_size); c->dark_wm = ALIGN(UBIFS_MAX_NODE_SZ, c->min_io_size); + /* + * Calculate how many bytes would be wasted at the end of LEB if it was + * fully filled with data nodes of maximum size. This is used in + * calculations when reporting free space. + */ + c->leb_overhead = c->leb_size % UBIFS_MAX_DATA_NODE_SZ; return 0; } diff --git a/fs/ubifs/ubifs.h b/fs/ubifs/ubifs.h index 681d46e..57e5854 100644 --- a/fs/ubifs/ubifs.h +++ b/fs/ubifs/ubifs.h @@ -995,6 +995,9 @@ struct ubifs_mount_opts { * @max_idx_node_sz: maximum indexing node aligned on 8-bytes boundary * @max_inode_sz: maximum possible inode size in bytes * @max_znode_sz: size of znode in bytes + * + * @leb_overhead: how many bytes are wasted in an LEB when it is filled with + * data nodes of maximum size - used in free space reporting * @dead_wm: LEB dead space watermark * @dark_wm: LEB dark space watermark * @block_cnt: count of 4KiB blocks on the FS @@ -1226,6 +1229,8 @@ struct ubifs_info { int max_idx_node_sz; long long max_inode_sz; int max_znode_sz; + + int leb_overhead; int dead_wm; int dark_wm; int block_cnt; -- cgit v0.10.2 From 7dad181bbe58b8fe9e170da28bcd5f6ec9addd6d Mon Sep 17 00:00:00 2001 From: Artem Bityutskiy Date: Mon, 25 Aug 2008 18:58:19 +0300 Subject: UBIFS: improve statfs reporting even more Since free space we report in statfs is file size which should fit to the FS - change the way we calculate free space and use leb_overhead instead of dark_wm in calculations. Results of "freespace" test (120MiB volume, 16KiB LEB size, 512 bytes page size). Before the change: freespace: Test 1: fill the space we have 3 times freespace: was free: 85204992 bytes 81.3 MiB, wrote: 96489472 bytes 92.0 MiB, delta: 11284480 bytes 10.8 MiB, wrote 13.2% more than predicted freespace: was free: 83554304 bytes 79.7 MiB, wrote: 96489472 bytes 92.0 MiB, delta: 12935168 bytes 12.3 MiB, wrote 15.5% more than predicted freespace: was free: 83554304 bytes 79.7 MiB, wrote: 96493568 bytes 92.0 MiB, delta: 12939264 bytes 12.3 MiB, wrote 15.5% more than predicted freespace: Test 1 finished freespace: Test 2: gradually lessen amount of free space and fill the FS freespace: do 10 steps, lessen free space by 7596218 bytes 7.2 MiB each time freespace: was free: 78675968 bytes 75.0 MiB, wrote: 88903680 bytes 84.8 MiB, delta: 10227712 bytes 9.8 MiB, wrote 13.0% more than predicted freespace: was free: 72015872 bytes 68.7 MiB, wrote: 81514496 bytes 77.7 MiB, delta: 9498624 bytes 9.1 MiB, wrote 13.2% more than predicted freespace: was free: 63938560 bytes 61.0 MiB, wrote: 72589312 bytes 69.2 MiB, delta: 8650752 bytes 8.2 MiB, wrote 13.5% more than predicted freespace: was free: 56127488 bytes 53.5 MiB, wrote: 63762432 bytes 60.8 MiB, delta: 7634944 bytes 7.3 MiB, wrote 13.6% more than predicted freespace: was free: 48336896 bytes 46.1 MiB, wrote: 54935552 bytes 52.4 MiB, delta: 6598656 bytes 6.3 MiB, wrote 13.7% more than predicted freespace: was free: 40587264 bytes 38.7 MiB, wrote: 46157824 bytes 44.0 MiB, delta: 5570560 bytes 5.3 MiB, wrote 13.7% more than predicted freespace: was free: 32841728 bytes 31.3 MiB, wrote: 37384192 bytes 35.7 MiB, delta: 4542464 bytes 4.3 MiB, wrote 13.8% more than predicted freespace: was free: 25100288 bytes 23.9 MiB, wrote: 28618752 bytes 27.3 MiB, delta: 3518464 bytes 3.4 MiB, wrote 14.0% more than predicted freespace: was free: 17342464 bytes 16.5 MiB, wrote: 19841024 bytes 18.9 MiB, delta: 2498560 bytes 2.4 MiB, wrote 14.4% more than predicted freespace: was free: 9605120 bytes 9.2 MiB, wrote: 11063296 bytes 10.6 MiB, delta: 1458176 bytes 1.4 MiB, wrote 15.2% more than predicted freespace: Test 2 finished freespace: Test 3: gradually lessen amount of free space by trashing and fill the FS freespace: do 10 steps, lessen free space by 7606272 bytes 7.3 MiB each time freespace: trashing: was free: 83668992 bytes 79.8 MiB, need free: 7606272 bytes 7.3 MiB, files created: 248297, delete 225724 (90.9% of them) freespace: was free: 70803456 bytes 67.5 MiB, wrote: 82485248 bytes 78.7 MiB, delta: 11681792 bytes 11.1 MiB, wrote 16.5% more than predicted freespace: trashing: was free: 81080320 bytes 77.3 MiB, need free: 15212544 bytes 14.5 MiB, files created: 248711, delete 202047 (81.2% of them) freespace: was free: 59867136 bytes 57.1 MiB, wrote: 71897088 bytes 68.6 MiB, delta: 12029952 bytes 11.5 MiB, wrote 20.1% more than predicted freespace: trashing: was free: 82243584 bytes 78.4 MiB, need free: 22818816 bytes 21.8 MiB, files created: 248866, delete 179817 (72.3% of them) freespace: was free: 50905088 bytes 48.5 MiB, wrote: 63168512 bytes 60.2 MiB, delta: 12263424 bytes 11.7 MiB, wrote 24.1% more than predicted freespace: trashing: was free: 83402752 bytes 79.5 MiB, need free: 30425088 bytes 29.0 MiB, files created: 248920, delete 158114 (63.5% of them) freespace: was free: 42651648 bytes 40.7 MiB, wrote: 55406592 bytes 52.8 MiB, delta: 12754944 bytes 12.2 MiB, wrote 29.9% more than predicted freespace: trashing: was free: 84402176 bytes 80.5 MiB, need free: 38031360 bytes 36.3 MiB, files created: 248709, delete 136641 (54.9% of them) freespace: was free: 35233792 bytes 33.6 MiB, wrote: 48250880 bytes 46.0 MiB, delta: 13017088 bytes 12.4 MiB, wrote 36.9% more than predicted freespace: trashing: was free: 82530304 bytes 78.7 MiB, need free: 45637632 bytes 43.5 MiB, files created: 248778, delete 111208 (44.7% of them) freespace: was free: 27287552 bytes 26.0 MiB, wrote: 40267776 bytes 38.4 MiB, delta: 12980224 bytes 12.4 MiB, wrote 47.6% more than predicted freespace: trashing: was free: 85114880 bytes 81.2 MiB, need free: 53243904 bytes 50.8 MiB, files created: 248508, delete 93052 (37.4% of them) freespace: was free: 22437888 bytes 21.4 MiB, wrote: 35328000 bytes 33.7 MiB, delta: 12890112 bytes 12.3 MiB, wrote 57.4% more than predicted freespace: trashing: was free: 84103168 bytes 80.2 MiB, need free: 60850176 bytes 58.0 MiB, files created: 248637, delete 68743 (27.6% of them) freespace: was free: 15536128 bytes 14.8 MiB, wrote: 28319744 bytes 27.0 MiB, delta: 12783616 bytes 12.2 MiB, wrote 82.3% more than predicted freespace: trashing: was free: 84357120 bytes 80.4 MiB, need free: 68456448 bytes 65.3 MiB, files created: 248567, delete 46852 (18.8% of them) freespace: was free: 9015296 bytes 8.6 MiB, wrote: 22044672 bytes 21.0 MiB, delta: 13029376 bytes 12.4 MiB, wrote 144.5% more than predicted freespace: trashing: was free: 84942848 bytes 81.0 MiB, need free: 76062720 bytes 72.5 MiB, files created: 248636, delete 25993 (10.5% of them) freespace: was free: 6086656 bytes 5.8 MiB, wrote: 8331264 bytes 7.9 MiB, delta: 2244608 bytes 2.1 MiB, wrote 36.9% more than predicted freespace: Test 3 finished freespace: finished successfully After the change: freespace: Test 1: fill the space we have 3 times freespace: was free: 94048256 bytes 89.7 MiB, wrote: 96489472 bytes 92.0 MiB, delta: 2441216 bytes 2.3 MiB, wrote 2.6% more than predicted freespace: was free: 92246016 bytes 88.0 MiB, wrote: 96493568 bytes 92.0 MiB, delta: 4247552 bytes 4.1 MiB, wrote 4.6% more than predicted freespace: was free: 92254208 bytes 88.0 MiB, wrote: 96489472 bytes 92.0 MiB, delta: 4235264 bytes 4.0 MiB, wrote 4.6% more than predicted freespace: Test 1 finished freespace: Test 2: gradually lessen amount of free space and fill the FS freespace: do 10 steps, lessen free space by 8386001 bytes 8.0 MiB each time freespace: was free: 86605824 bytes 82.6 MiB, wrote: 88252416 bytes 84.2 MiB, delta: 1646592 bytes 1.6 MiB, wrote 1.9% more than predicted freespace: was free: 78667776 bytes 75.0 MiB, wrote: 80715776 bytes 77.0 MiB, delta: 2048000 bytes 2.0 MiB, wrote 2.6% more than predicted freespace: was free: 69615616 bytes 66.4 MiB, wrote: 71630848 bytes 68.3 MiB, delta: 2015232 bytes 1.9 MiB, wrote 2.9% more than predicted freespace: was free: 61018112 bytes 58.2 MiB, wrote: 62783488 bytes 59.9 MiB, delta: 1765376 bytes 1.7 MiB, wrote 2.9% more than predicted freespace: was free: 52424704 bytes 50.0 MiB, wrote: 53968896 bytes 51.5 MiB, delta: 1544192 bytes 1.5 MiB, wrote 2.9% more than predicted freespace: was free: 43880448 bytes 41.8 MiB, wrote: 45199360 bytes 43.1 MiB, delta: 1318912 bytes 1.3 MiB, wrote 3.0% more than predicted freespace: was free: 35332096 bytes 33.7 MiB, wrote: 36425728 bytes 34.7 MiB, delta: 1093632 bytes 1.0 MiB, wrote 3.1% more than predicted freespace: was free: 26771456 bytes 25.5 MiB, wrote: 27643904 bytes 26.4 MiB, delta: 872448 bytes 852.0 KiB, wrote 3.3% more than predicted freespace: was free: 18231296 bytes 17.4 MiB, wrote: 18878464 bytes 18.0 MiB, delta: 647168 bytes 632.0 KiB, wrote 3.5% more than predicted freespace: was free: 9674752 bytes 9.2 MiB, wrote: 10088448 bytes 9.6 MiB, delta: 413696 bytes 404.0 KiB, wrote 4.3% more than predicted freespace: Test 2 finished freespace: Test 3: gradually lessen amount of free space by trashing and fill the FS freespace: do 10 steps, lessen free space by 8397544 bytes 8.0 MiB each time freespace: trashing: was free: 92372992 bytes 88.1 MiB, need free: 8397552 bytes 8.0 MiB, files created: 248296, delete 225723 (90.9% of them) freespace: was free: 71909376 bytes 68.6 MiB, wrote: 82472960 bytes 78.7 MiB, delta: 10563584 bytes 10.1 MiB, wrote 14.7% more than predicted freespace: trashing: was free: 88989696 bytes 84.9 MiB, need free: 16795096 bytes 16.0 MiB, files created: 248794, delete 201838 (81.1% of them) freespace: was free: 60354560 bytes 57.6 MiB, wrote: 71782400 bytes 68.5 MiB, delta: 11427840 bytes 10.9 MiB, wrote 18.9% more than predicted freespace: trashing: was free: 90304512 bytes 86.1 MiB, need free: 25192640 bytes 24.0 MiB, files created: 248733, delete 179342 (72.1% of them) freespace: was free: 51187712 bytes 48.8 MiB, wrote: 62943232 bytes 60.0 MiB, delta: 11755520 bytes 11.2 MiB, wrote 23.0% more than predicted freespace: trashing: was free: 91209728 bytes 87.0 MiB, need free: 33590184 bytes 32.0 MiB, files created: 248779, delete 157160 (63.2% of them) freespace: was free: 42704896 bytes 40.7 MiB, wrote: 55050240 bytes 52.5 MiB, delta: 12345344 bytes 11.8 MiB, wrote 28.9% more than predicted freespace: trashing: was free: 92700672 bytes 88.4 MiB, need free: 41987728 bytes 40.0 MiB, files created: 248848, delete 136135 (54.7% of them) freespace: was free: 35250176 bytes 33.6 MiB, wrote: 48115712 bytes 45.9 MiB, delta: 12865536 bytes 12.3 MiB, wrote 36.5% more than predicted freespace: trashing: was free: 93986816 bytes 89.6 MiB, need free: 50385272 bytes 48.1 MiB, files created: 248723, delete 115385 (46.4% of them) freespace: was free: 29995008 bytes 28.6 MiB, wrote: 41582592 bytes 39.7 MiB, delta: 11587584 bytes 11.1 MiB, wrote 38.6% more than predicted freespace: trashing: was free: 91881472 bytes 87.6 MiB, need free: 58782816 bytes 56.1 MiB, files created: 248645, delete 89569 (36.0% of them) freespace: was free: 22511616 bytes 21.5 MiB, wrote: 34705408 bytes 33.1 MiB, delta: 12193792 bytes 11.6 MiB, wrote 54.2% more than predicted freespace: trashing: was free: 91774976 bytes 87.5 MiB, need free: 67180360 bytes 64.1 MiB, files created: 248580, delete 66616 (26.8% of them) freespace: was free: 16908288 bytes 16.1 MiB, wrote: 26898432 bytes 25.7 MiB, delta: 9990144 bytes 9.5 MiB, wrote 59.1% more than predicted freespace: trashing: was free: 92450816 bytes 88.2 MiB, need free: 75577904 bytes 72.1 MiB, files created: 248654, delete 45381 (18.3% of them) freespace: was free: 10170368 bytes 9.7 MiB, wrote: 19111936 bytes 18.2 MiB, delta: 8941568 bytes 8.5 MiB, wrote 87.9% more than predicted freespace: trashing: was free: 93282304 bytes 89.0 MiB, need free: 83975448 bytes 80.1 MiB, files created: 248513, delete 24794 (10.0% of them) freespace: was free: 3911680 bytes 3.7 MiB, wrote: 7872512 bytes 7.5 MiB, delta: 3960832 bytes 3.8 MiB, wrote 101.3% more than predicted freespace: Test 3 finished freespace: finished successfully Signed-off-by: Artem Bityutskiy diff --git a/fs/ubifs/budget.c b/fs/ubifs/budget.c index 7851480..101d278 100644 --- a/fs/ubifs/budget.c +++ b/fs/ubifs/budget.c @@ -747,14 +747,24 @@ long long ubifs_reported_space(const struct ubifs_info *c, uint64_t free) } /** - * ubifs_budg_get_free_space - return amount of free space. + * ubifs_get_free_space - return amount of free space. * @c: UBIFS file-system description object * - * This function returns amount of free space on the file-system. + * This function calculates amount of free space to report to user-space. + * + * Because UBIFS may introduce substantial overhead (the index, node headers, + * alighment, wastage at the end of eraseblocks, etc), it cannot report real + * amount of free flash space it has (well, because not all dirty space is + * reclamable, UBIFS does not actually know the real amount). If UBIFS did so, + * it would bread user expectetion about what free space is. Users seem to + * accustomed to assume that if the file-system reports N bytes of free space, + * they would be able to fit a file of N bytes to the FS. This almost works for + * traditional file-systems, because they have way less overhead than UBIFS. + * So, to keep users happy, UBIFS tries to take the overhead into account. */ -long long ubifs_budg_get_free_space(struct ubifs_info *c) +long long ubifs_get_free_space(struct ubifs_info *c) { - int min_idx_lebs; + int min_idx_lebs, rsvd_idx_lebs, lebs; long long available, outstanding, free; spin_lock(&c->space_lock); @@ -771,6 +781,26 @@ long long ubifs_budg_get_free_space(struct ubifs_info *c) } available = ubifs_calc_available(c, min_idx_lebs); + + /* + * When reporting free space to user-space, UBIFS guarantees that it is + * possible to write a file of free space size. This means that for + * empty LEBs we may use more precise calculations than + * 'ubifs_calc_available()' is using. Namely, we know that in empty + * LEBs we would waste only @c->leb_overhead bytes, not @c->dark_wm. + * Thus, amend the available space. + * + * Note, the calculations below are similar to what we have in + * 'do_budget_space()', so refer there for comments. + */ + if (min_idx_lebs > c->lst.idx_lebs) + rsvd_idx_lebs = min_idx_lebs - c->lst.idx_lebs; + else + rsvd_idx_lebs = 0; + lebs = c->lst.empty_lebs + c->freeable_cnt + c->idx_gc_cnt - + c->lst.taken_empty_lebs; + lebs -= rsvd_idx_lebs; + available += lebs * (c->dark_wm - c->leb_overhead); spin_unlock(&c->space_lock); if (available > outstanding) diff --git a/fs/ubifs/super.c b/fs/ubifs/super.c index be23fd3..1207bd5 100644 --- a/fs/ubifs/super.c +++ b/fs/ubifs/super.c @@ -371,7 +371,7 @@ static int ubifs_statfs(struct dentry *dentry, struct kstatfs *buf) struct ubifs_info *c = dentry->d_sb->s_fs_info; unsigned long long free; - free = ubifs_budg_get_free_space(c); + free = ubifs_get_free_space(c); dbg_gen("free space %lld bytes (%lld blocks)", free, free >> UBIFS_BLOCK_SHIFT); @@ -653,11 +653,11 @@ static int init_constants_late(struct ubifs_info *c) * internally because it does not make much sense for UBIFS, but it is * necessary to report something for the 'statfs()' call. * - * Subtract the LEB reserved for GC and the LEB which is reserved for - * deletions. + * Subtract the LEB reserved for GC, the LEB which is reserved for + * deletions, and assume only one journal head is available. */ - tmp64 = c->main_lebs - 2; - tmp64 *= (uint64_t)c->leb_size - c->dark_wm; + tmp64 = c->main_lebs - 2 - c->jhead_cnt + 1; + tmp64 *= (uint64_t)c->leb_size - c->leb_overhead; tmp64 = ubifs_reported_space(c, tmp64); c->block_cnt = tmp64 >> UBIFS_BLOCK_SHIFT; diff --git a/fs/ubifs/ubifs.h b/fs/ubifs/ubifs.h index 57e5854..17c620b 100644 --- a/fs/ubifs/ubifs.h +++ b/fs/ubifs/ubifs.h @@ -1443,7 +1443,7 @@ void ubifs_release_ino_dirty(struct ubifs_info *c, struct inode *inode, struct ubifs_budget_req *req); void ubifs_cancel_ino_op(struct ubifs_info *c, struct inode *inode, struct ubifs_budget_req *req); -long long ubifs_budg_get_free_space(struct ubifs_info *c); +long long ubifs_get_free_space(struct ubifs_info *c); int ubifs_calc_min_idx_lebs(struct ubifs_info *c); void ubifs_convert_page_budget(struct ubifs_info *c); long long ubifs_reported_space(const struct ubifs_info *c, uint64_t free); -- cgit v0.10.2 From b3385c278d3c32aec68d4900b35bc07df1b2240c Mon Sep 17 00:00:00 2001 From: Artem Bityutskiy Date: Sun, 31 Aug 2008 17:13:18 +0300 Subject: UBIFS: fill f_fsid UBIFS stores 16-bit UUID in the superblock, and it is a good idea to return part of it in 'f_fsid' filed of kstatfs structure. Signed-off-by: Artem Bityutskiy diff --git a/fs/ubifs/super.c b/fs/ubifs/super.c index 1207bd5..0dee404 100644 --- a/fs/ubifs/super.c +++ b/fs/ubifs/super.c @@ -386,6 +386,7 @@ static int ubifs_statfs(struct dentry *dentry, struct kstatfs *buf) buf->f_files = 0; buf->f_ffree = 0; buf->f_namelen = UBIFS_MAX_NLEN; + memcpy(&buf->f_fsid, c->uuid, sizeof(__kernel_fsid_t)); return 0; } -- cgit v0.10.2 From 673d62cc5ea6fca046650f17f77985b112c62322 Mon Sep 17 00:00:00 2001 From: Vegard Nossum Date: Sun, 31 Aug 2008 23:39:21 +0200 Subject: debugobjects: fix lockdep warning Daniel J. Blueman reported: > ======================================================= > [ INFO: possible circular locking dependency detected ] > 2.6.27-rc4-224c #1 > ------------------------------------------------------- > hald/4680 is trying to acquire lock: > (&n->list_lock){++..}, at: [] add_partial+0x26/0x80 > > but task is already holding lock: > (&obj_hash[i].lock){++..}, at: [] > debug_object_free+0x5c/0x120 We fix it by moving the actual freeing to outside the lock (the lock now only protects the list). The pool lock is also promoted to irq-safe (suggested by Dan). It's necessary because free_pool is now called outside the irq disabled region. So we need to protect against an interrupt handler which calls debug_object_init(). [tglx@linutronix.de: added hlist_move_list helper to avoid looping through the list twice] Reported-by: Daniel J Blueman Signed-off-by: Vegard Nossum Signed-off-by: Thomas Gleixner diff --git a/include/linux/list.h b/include/linux/list.h index db35ef0..969f6e9 100644 --- a/include/linux/list.h +++ b/include/linux/list.h @@ -619,6 +619,19 @@ static inline void hlist_add_after(struct hlist_node *n, next->next->pprev = &next->next; } +/* + * Move a list from one list head to another. Fixup the pprev + * reference of the first entry if it exists. + */ +static inline void hlist_move_list(struct hlist_head *old, + struct hlist_head *new) +{ + new->first = old->first; + if (new->first) + new->first->pprev = &new->first; + old->first = NULL; +} + #define hlist_entry(ptr, type, member) container_of(ptr,type,member) #define hlist_for_each(pos, head) \ diff --git a/lib/debugobjects.c b/lib/debugobjects.c index 45a6bde..e3ab374 100644 --- a/lib/debugobjects.c +++ b/lib/debugobjects.c @@ -112,6 +112,7 @@ static struct debug_obj *lookup_object(void *addr, struct debug_bucket *b) /* * Allocate a new object. If the pool is empty, switch off the debugger. + * Must be called with interrupts disabled. */ static struct debug_obj * alloc_object(void *addr, struct debug_bucket *b, struct debug_obj_descr *descr) @@ -148,17 +149,18 @@ alloc_object(void *addr, struct debug_bucket *b, struct debug_obj_descr *descr) static void free_object(struct debug_obj *obj) { unsigned long idx = (unsigned long)(obj - obj_static_pool); + unsigned long flags; if (obj_pool_free < ODEBUG_POOL_SIZE || idx < ODEBUG_POOL_SIZE) { - spin_lock(&pool_lock); + spin_lock_irqsave(&pool_lock, flags); hlist_add_head(&obj->node, &obj_pool); obj_pool_free++; obj_pool_used--; - spin_unlock(&pool_lock); + spin_unlock_irqrestore(&pool_lock, flags); } else { - spin_lock(&pool_lock); + spin_lock_irqsave(&pool_lock, flags); obj_pool_used--; - spin_unlock(&pool_lock); + spin_unlock_irqrestore(&pool_lock, flags); kmem_cache_free(obj_cache, obj); } } @@ -171,6 +173,7 @@ static void debug_objects_oom(void) { struct debug_bucket *db = obj_hash; struct hlist_node *node, *tmp; + HLIST_HEAD(freelist); struct debug_obj *obj; unsigned long flags; int i; @@ -179,11 +182,14 @@ static void debug_objects_oom(void) for (i = 0; i < ODEBUG_HASH_SIZE; i++, db++) { spin_lock_irqsave(&db->lock, flags); - hlist_for_each_entry_safe(obj, node, tmp, &db->list, node) { + hlist_move_list(&db->list, &freelist); + spin_unlock_irqrestore(&db->lock, flags); + + /* Now free them */ + hlist_for_each_entry_safe(obj, node, tmp, &freelist, node) { hlist_del(&obj->node); free_object(obj); } - spin_unlock_irqrestore(&db->lock, flags); } } @@ -498,8 +504,9 @@ void debug_object_free(void *addr, struct debug_obj_descr *descr) return; default: hlist_del(&obj->node); + spin_unlock_irqrestore(&db->lock, flags); free_object(obj); - break; + return; } out_unlock: spin_unlock_irqrestore(&db->lock, flags); @@ -510,6 +517,7 @@ static void __debug_check_no_obj_freed(const void *address, unsigned long size) { unsigned long flags, oaddr, saddr, eaddr, paddr, chunks; struct hlist_node *node, *tmp; + HLIST_HEAD(freelist); struct debug_obj_descr *descr; enum debug_obj_state state; struct debug_bucket *db; @@ -545,11 +553,18 @@ repeat: goto repeat; default: hlist_del(&obj->node); - free_object(obj); + hlist_add_head(&obj->node, &freelist); break; } } spin_unlock_irqrestore(&db->lock, flags); + + /* Now free them */ + hlist_for_each_entry_safe(obj, node, tmp, &freelist, node) { + hlist_del(&obj->node); + free_object(obj); + } + if (cnt > debug_objects_maxchain) debug_objects_maxchain = cnt; } -- cgit v0.10.2 From 9e3f544d792fd2ff7e31ca4a72e5194f1491ed14 Mon Sep 17 00:00:00 2001 From: Haavard Skinnemoen Date: Wed, 20 Aug 2008 15:46:24 +0200 Subject: avr32: Fix lockup after Java stack underflow in user mode When using the Java Extension Module hardware, a Java stack underflow or overflow trap may cause the system to enter an infinite exception loop. Although there's no kernel support for the Java hardware yet, we need to be able to recover from this situation and keep the system running. This patch adds code to detect and fixup this situation in the critical exception handler and terminate the faulting process. We may have to rethink how to handle this more gracefully when the necessary kernel support for hardware-accelerated Java is added. Reported-by: Guennadi Liakhovetski Signed-off-by: Haavard Skinnemoen diff --git a/arch/avr32/kernel/asm-offsets.c b/arch/avr32/kernel/asm-offsets.c index e4796c6..d6a8193 100644 --- a/arch/avr32/kernel/asm-offsets.c +++ b/arch/avr32/kernel/asm-offsets.c @@ -4,6 +4,8 @@ * to extract and format the required data. */ +#include +#include #include #include @@ -17,4 +19,8 @@ void foo(void) OFFSET(TI_rar_saved, thread_info, rar_saved); OFFSET(TI_rsr_saved, thread_info, rsr_saved); OFFSET(TI_restart_block, thread_info, restart_block); + BLANK(); + OFFSET(TSK_active_mm, task_struct, active_mm); + BLANK(); + OFFSET(MM_pgd, mm_struct, pgd); } diff --git a/arch/avr32/kernel/entry-avr32b.S b/arch/avr32/kernel/entry-avr32b.S index 2b398ca..33d4937 100644 --- a/arch/avr32/kernel/entry-avr32b.S +++ b/arch/avr32/kernel/entry-avr32b.S @@ -334,9 +334,64 @@ save_full_context_ex: /* Low-level exception handlers */ handle_critical: + /* + * AT32AP700x errata: + * + * After a Java stack overflow or underflow trap, any CPU + * memory access may cause erratic behavior. This will happen + * when the four least significant bits of the JOSP system + * register contains any value between 9 and 15 (inclusive). + * + * Possible workarounds: + * - Don't use the Java Extension Module + * - Ensure that the stack overflow and underflow trap + * handlers do not do any memory access or trigger any + * exceptions before the overflow/underflow condition is + * cleared (by incrementing or decrementing the JOSP) + * - Make sure that JOSP does not contain any problematic + * value before doing any exception or interrupt + * processing. + * - Set up a critical exception handler which writes a + * known-to-be-safe value, e.g. 4, to JOSP before doing + * any further processing. + * + * We'll use the last workaround for now since we cannot + * guarantee that user space processes don't use Java mode. + * Non-well-behaving userland will be terminated with extreme + * prejudice. + */ +#ifdef CONFIG_CPU_AT32AP700X + /* + * There's a chance we can't touch memory, so temporarily + * borrow PTBR to save the stack pointer while we fix things + * up... + */ + mtsr SYSREG_PTBR, sp + mov sp, 4 + mtsr SYSREG_JOSP, sp + mfsr sp, SYSREG_PTBR + sub pc, -2 + + /* Push most of pt_regs on stack. We'll do the rest later */ sub sp, 4 - stmts --sp, r0-lr - rcall save_full_context_ex + pushm r0-r12 + + /* PTBR mirrors current_thread_info()->task->active_mm->pgd */ + get_thread_info r0 + ld.w r1, r0[TI_task] + ld.w r2, r1[TSK_active_mm] + ld.w r3, r2[MM_pgd] + mtsr SYSREG_PTBR, r3 +#else + sub sp, 4 + pushm r0-r12 +#endif + sub r0, sp, -(14 * 4) + mov r1, lr + mfsr r2, SYSREG_RAR_EX + mfsr r3, SYSREG_RSR_EX + pushm r0-r3 + mfsr r12, SYSREG_ECR mov r11, sp rcall do_critical_exception -- cgit v0.10.2 From 84c4f2f21a8e6e6d4bdfff95bf5ddc7925df4e01 Mon Sep 17 00:00:00 2001 From: Humphrey Bucknell Date: Fri, 29 Aug 2008 16:27:00 +0100 Subject: avr32: pm_standby low-power ram bug fix The value stored into the SDRAMC LPR register should be the current value of the register with the Self-refresh value set in the lower bit field. The bug involved only the Self-refresh value being written to the register, thus over writing any low-power ram settings. Signed-off-by: Humphrey Bucknell Signed-off-by: Haavard Skinnemoen diff --git a/arch/avr32/mach-at32ap/pm-at32ap700x.S b/arch/avr32/mach-at32ap/pm-at32ap700x.S index 5be4de6..17503b0 100644 --- a/arch/avr32/mach-at32ap/pm-at32ap700x.S +++ b/arch/avr32/mach-at32ap/pm-at32ap700x.S @@ -134,7 +134,7 @@ pm_standby: mov r11, SDRAMC_LPR_LPCB_SELF_RFR bfins r10, r11, 0, 2 /* LPCB <- self Refresh */ sync 0 /* flush write buffer */ - st.w r12[SDRAMC_LPR], r11 /* put SDRAM in self-refresh mode */ + st.w r12[SDRAMC_LPR], r10 /* put SDRAM in self-refresh mode */ ld.w r11, r12[SDRAMC_LPR] unmask_interrupts sleep CPU_SLEEP_FROZEN -- cgit v0.10.2 From e5bd1c3fdd06b6c0fa6dfb98ce31cea1820ce4e9 Mon Sep 17 00:00:00 2001 From: "David S. Miller" Date: Wed, 3 Sep 2008 02:14:39 -0700 Subject: sparc64: Fix IPI call locking. When I switched sparc64 over to the generic helpers for smp_call_function(), I didn't convert the dinky call_lock we had. Use ipi_call_lock() and ipi_call_unlock(). Signed-off-by: David S. Miller diff --git a/arch/sparc64/kernel/smp.c b/arch/sparc64/kernel/smp.c index 743ccad..0712a44 100644 --- a/arch/sparc64/kernel/smp.c +++ b/arch/sparc64/kernel/smp.c @@ -80,8 +80,6 @@ void smp_bogo(struct seq_file *m) i, cpu_data(i).clock_tick); } -static __cacheline_aligned_in_smp DEFINE_SPINLOCK(call_lock); - extern void setup_sparc64_timer(void); static volatile unsigned long callin_flag = 0; @@ -120,9 +118,9 @@ void __cpuinit smp_callin(void) while (!cpu_isset(cpuid, smp_commenced_mask)) rmb(); - spin_lock(&call_lock); + ipi_call_lock(); cpu_set(cpuid, cpu_online_map); - spin_unlock(&call_lock); + ipi_call_unlock(); /* idle thread is expected to have preempt disabled */ preempt_disable(); @@ -1305,9 +1303,9 @@ int __cpu_disable(void) c->core_id = 0; c->proc_id = -1; - spin_lock(&call_lock); + ipi_call_lock(); cpu_clear(cpu, cpu_online_map); - spin_unlock(&call_lock); + ipi_call_unlock(); smp_wmb(); -- cgit v0.10.2 From 69114a47af524badc73de8fc86959941a03f0600 Mon Sep 17 00:00:00 2001 From: Russell King Date: Wed, 3 Sep 2008 10:15:26 +0100 Subject: [ARM] omap: fix gpio.c build error arch/arm/plat-omap/gpio.c: In function '_omap_gpio_init': arch/arm/plat-omap/gpio.c:1492: error: 'omap_mpuio_device' undeclared (first use in this function) Signed-off-by: Russell King diff --git a/arch/arm/plat-omap/gpio.c b/arch/arm/plat-omap/gpio.c index 3e76ee2..9e1341e 100644 --- a/arch/arm/plat-omap/gpio.c +++ b/arch/arm/plat-omap/gpio.c @@ -1488,7 +1488,7 @@ static int __init _omap_gpio_init(void) bank->chip.set = gpio_set; if (bank_is_mpuio(bank)) { bank->chip.label = "mpuio"; -#ifdef CONFIG_ARCH_OMAP1 +#ifdef CONFIG_ARCH_OMAP16XX bank->chip.dev = &omap_mpuio_device.dev; #endif bank->chip.base = OMAP_MPUIO(0); -- cgit v0.10.2 From 4d084617fb0d025c42c242362d1f27d337e2d407 Mon Sep 17 00:00:00 2001 From: "Paul E. McKenney" Date: Wed, 3 Sep 2008 02:15:30 -0700 Subject: sparc64: Prevent sparc64 from invoking irq handlers on offline CPUs Make sparc64 refrain from clearing a given to-be-offlined CPU's bit in the cpu_online_mask until it has processed pending irqs. This change prevents other CPUs from being blindsided by an apparently offline CPU nevertheless changing globally visible state. Signed-off-by: Paul E. McKenney Signed-off-by: David S. Miller diff --git a/arch/sparc64/kernel/smp.c b/arch/sparc64/kernel/smp.c index 0712a44..2be166c 100644 --- a/arch/sparc64/kernel/smp.c +++ b/arch/sparc64/kernel/smp.c @@ -1303,10 +1303,6 @@ int __cpu_disable(void) c->core_id = 0; c->proc_id = -1; - ipi_call_lock(); - cpu_clear(cpu, cpu_online_map); - ipi_call_unlock(); - smp_wmb(); /* Make sure no interrupts point to this cpu. */ @@ -1316,6 +1312,10 @@ int __cpu_disable(void) mdelay(1); local_irq_disable(); + ipi_call_lock(); + cpu_clear(cpu, cpu_online_map); + ipi_call_unlock(); + return 0; } -- cgit v0.10.2 From 7c7cbadf7341a0792879c67d6e3020f040d6cd7f Mon Sep 17 00:00:00 2001 From: Artem Bityutskiy Date: Wed, 3 Sep 2008 14:16:42 +0300 Subject: UBIFS: amend f_fsid David Woodhouse suggested to be consistent with other FSes and xor the beginning and the end of the UUID. Signed-off-by: Artem Bityutskiy diff --git a/fs/ubifs/super.c b/fs/ubifs/super.c index 0dee404..7562464 100644 --- a/fs/ubifs/super.c +++ b/fs/ubifs/super.c @@ -370,6 +370,7 @@ static int ubifs_statfs(struct dentry *dentry, struct kstatfs *buf) { struct ubifs_info *c = dentry->d_sb->s_fs_info; unsigned long long free; + __le32 *uuid = (__le32 *)c->uuid; free = ubifs_get_free_space(c); dbg_gen("free space %lld bytes (%lld blocks)", @@ -386,8 +387,8 @@ static int ubifs_statfs(struct dentry *dentry, struct kstatfs *buf) buf->f_files = 0; buf->f_ffree = 0; buf->f_namelen = UBIFS_MAX_NLEN; - memcpy(&buf->f_fsid, c->uuid, sizeof(__kernel_fsid_t)); - + buf->f_fsid.val[0] = le32_to_cpu(uuid[0]) ^ le32_to_cpu(uuid[2]); + buf->f_fsid.val[1] = le32_to_cpu(uuid[1]) ^ le32_to_cpu(uuid[3]); return 0; } -- cgit v0.10.2 From 2e7acd75cba3b7afa4007f20f22a86dbbdb21753 Mon Sep 17 00:00:00 2001 From: Michael Krufky Date: Wed, 3 Sep 2008 16:46:35 -0300 Subject: V4L/DVB (8555): au8522: add mechanism to configure IF frequency for vsb and qam Add a mechanism to configure IF frequency for vsb and qam. Signed-off-by: Michael Krufky Signed-off-by: Mauro Carvalho Chehab diff --git a/drivers/media/dvb/frontends/au8522.c b/drivers/media/dvb/frontends/au8522.c index f7b7165..5741bc9 100644 --- a/drivers/media/dvb/frontends/au8522.c +++ b/drivers/media/dvb/frontends/au8522.c @@ -304,6 +304,70 @@ static int au8522_mse2snr_lookup(struct mse2snr_tab *tab, int sz, int mse, return ret; } +/* 3.25 MHz IF Frequency table */ +static struct { + u16 reg; + u16 data; +} if_3_25_mhz_tab[] = { + { 0x80b5, 0x00 }, + { 0x80b6, 0x3d }, + { 0x80b7, 0xa0 }, +}; + +/* 4.00 MHz IF Frequency table */ +static struct { + u16 reg; + u16 data; +} if_4_mhz_tab[] = { + { 0x80b5, 0x00 }, + { 0x80b6, 0x4b }, + { 0x80b7, 0xd9 }, +}; + +/* 6.00 MHz IF Frequency table */ +static struct { + u16 reg; + u16 data; +} if_6_mhz_tab[] = { + { 0x80b5, 0xfb }, + { 0x80b6, 0x8e }, + { 0x80b7, 0x39 }, +}; + +static int au8522_set_if(struct dvb_frontend *fe, enum au8522_if_freq if_freq) +{ + struct au8522_state *state = fe->demodulator_priv; + int i; + + switch (if_freq) { + case AU8522_IF_3_25MHZ: + dprintk("%s() 3.25 MHz\n", __func__); + for (i = 0; i < ARRAY_SIZE(if_3_25_mhz_tab); i++) + au8522_writereg(state, + if_3_25_mhz_tab[i].reg, + if_3_25_mhz_tab[i].data); + break; + case AU8522_IF_4MHZ: + dprintk("%s() 4.00 MHz\n", __func__); + for (i = 0; i < ARRAY_SIZE(if_4_mhz_tab); i++) + au8522_writereg(state, + if_4_mhz_tab[i].reg, + if_4_mhz_tab[i].data); + break; + case AU8522_IF_6MHZ: + dprintk("%s() 6.00 MHz\n", __func__); + for (i = 0; i < ARRAY_SIZE(if_6_mhz_tab); i++) + au8522_writereg(state, + if_6_mhz_tab[i].reg, + if_6_mhz_tab[i].data); + break; + default: + dprintk("%s() IF Frequency not supported\n", __func__); + return -EINVAL; + } + return 0; +} + /* VSB Modulation table */ static struct { u16 reg; @@ -438,6 +502,7 @@ static int au8522_enable_modulation(struct dvb_frontend *fe, au8522_writereg(state, VSB_mod_tab[i].reg, VSB_mod_tab[i].data); + au8522_set_if(fe, state->config->vsb_if); break; case QAM_64: case QAM_256: @@ -446,6 +511,7 @@ static int au8522_enable_modulation(struct dvb_frontend *fe, au8522_writereg(state, QAM_mod_tab[i].reg, QAM_mod_tab[i].data); + au8522_set_if(fe, state->config->qam_if); break; default: dprintk("%s() Invalid modulation\n", __func__); diff --git a/drivers/media/dvb/frontends/au8522.h b/drivers/media/dvb/frontends/au8522.h index d7affa3..afc9af2 100644 --- a/drivers/media/dvb/frontends/au8522.h +++ b/drivers/media/dvb/frontends/au8522.h @@ -24,6 +24,12 @@ #include +enum au8522_if_freq { + AU8522_IF_6MHZ = 0, + AU8522_IF_4MHZ, + AU8522_IF_3_25MHZ, +}; + struct au8522_config { /* the demodulator's i2c address */ u8 demod_address; @@ -32,6 +38,9 @@ struct au8522_config { #define AU8522_TUNERLOCKING 0 #define AU8522_DEMODLOCKING 1 u8 status_mode; + + enum au8522_if_freq vsb_if; + enum au8522_if_freq qam_if; }; #if defined(CONFIG_DVB_AU8522) || \ -- cgit v0.10.2 From 8e8bd229eef385ab420d4fa51c611d4ddc7cb0c8 Mon Sep 17 00:00:00 2001 From: Michael Krufky Date: Wed, 3 Sep 2008 16:46:36 -0300 Subject: V4L/DVB (8556): au0828: add support for Hauppauge Woodbury Signed-off-by: Michael Krufky Signed-off-by: Mauro Carvalho Chehab diff --git a/Documentation/video4linux/CARDLIST.au0828 b/Documentation/video4linux/CARDLIST.au0828 index eedc399..aa05e5b 100644 --- a/Documentation/video4linux/CARDLIST.au0828 +++ b/Documentation/video4linux/CARDLIST.au0828 @@ -3,3 +3,4 @@ 2 -> Hauppauge HVR850 (au0828) [2040:7240] 3 -> DViCO FusionHDTV USB (au0828) [0fe9:d620] 4 -> Hauppauge HVR950Q rev xxF8 (au0828) [2040:7201,2040:7211,2040:7281] + 5 -> Hauppauge Woodbury (au0828) [2040:8200] diff --git a/drivers/media/video/au0828/Kconfig b/drivers/media/video/au0828/Kconfig index ed9a50f..018f72b 100644 --- a/drivers/media/video/au0828/Kconfig +++ b/drivers/media/video/au0828/Kconfig @@ -7,6 +7,7 @@ config VIDEO_AU0828 select DVB_AU8522 if !DVB_FE_CUSTOMIZE select MEDIA_TUNER_XC5000 if !DVB_FE_CUSTOMIZE select MEDIA_TUNER_MXL5007T if !DVB_FE_CUSTOMIZE + select MEDIA_TUNER_TDA18271 if !DVB_FE_CUSTOMIZE ---help--- This is a video4linux driver for Auvitek's USB device. diff --git a/drivers/media/video/au0828/au0828-cards.c b/drivers/media/video/au0828/au0828-cards.c index 443e590..14b9fc9 100644 --- a/drivers/media/video/au0828/au0828-cards.c +++ b/drivers/media/video/au0828/au0828-cards.c @@ -38,6 +38,9 @@ struct au0828_board au0828_boards[] = { [AU0828_BOARD_DVICO_FUSIONHDTV7] = { .name = "DViCO FusionHDTV USB", }, + [AU0828_BOARD_HAUPPAUGE_WOODBURY] = { + .name = "Hauppauge Woodbury", + }, }; /* Tuner callback function for au0828 boards. Currently only needed @@ -115,6 +118,7 @@ void au0828_card_setup(struct au0828_dev *dev) case AU0828_BOARD_HAUPPAUGE_HVR850: case AU0828_BOARD_HAUPPAUGE_HVR950Q: case AU0828_BOARD_HAUPPAUGE_HVR950Q_MXL: + case AU0828_BOARD_HAUPPAUGE_WOODBURY: if (dev->i2c_rc == 0) hauppauge_eeprom(dev, eeprom+0xa0); break; @@ -134,6 +138,7 @@ void au0828_gpio_setup(struct au0828_dev *dev) case AU0828_BOARD_HAUPPAUGE_HVR850: case AU0828_BOARD_HAUPPAUGE_HVR950Q: case AU0828_BOARD_HAUPPAUGE_HVR950Q_MXL: + case AU0828_BOARD_HAUPPAUGE_WOODBURY: /* GPIO's * 4 - CS5340 * 5 - AU8522 Demodulator @@ -205,6 +210,8 @@ struct usb_device_id au0828_usb_id_table [] = { .driver_info = AU0828_BOARD_HAUPPAUGE_HVR950Q_MXL }, { USB_DEVICE(0x2040, 0x7281), .driver_info = AU0828_BOARD_HAUPPAUGE_HVR950Q_MXL }, + { USB_DEVICE(0x2040, 0x8200), + .driver_info = AU0828_BOARD_HAUPPAUGE_WOODBURY }, { }, }; diff --git a/drivers/media/video/au0828/au0828-cards.h b/drivers/media/video/au0828/au0828-cards.h index c37f5fd..102ed03 100644 --- a/drivers/media/video/au0828/au0828-cards.h +++ b/drivers/media/video/au0828/au0828-cards.h @@ -24,3 +24,4 @@ #define AU0828_BOARD_HAUPPAUGE_HVR850 2 #define AU0828_BOARD_DVICO_FUSIONHDTV7 3 #define AU0828_BOARD_HAUPPAUGE_HVR950Q_MXL 4 +#define AU0828_BOARD_HAUPPAUGE_WOODBURY 5 diff --git a/drivers/media/video/au0828/au0828-dvb.c b/drivers/media/video/au0828/au0828-dvb.c index 584a83a..c862f9e 100644 --- a/drivers/media/video/au0828/au0828-dvb.c +++ b/drivers/media/video/au0828/au0828-dvb.c @@ -29,6 +29,7 @@ #include "au8522.h" #include "xc5000.h" #include "mxl5007t.h" +#include "tda18271.h" DVB_DEFINE_MOD_OPT_ADAPTER_NR(adapter_nr); @@ -40,6 +41,13 @@ static struct au8522_config hauppauge_hvr950q_config = { .status_mode = AU8522_DEMODLOCKING, }; +static struct au8522_config hauppauge_woodbury_config = { + .demod_address = 0x8e >> 1, + .status_mode = AU8522_DEMODLOCKING, + .qam_if = AU8522_IF_4MHZ, + .vsb_if = AU8522_IF_3_25MHZ, +}; + static struct xc5000_config hauppauge_hvr950q_tunerconfig = { .i2c_address = 0x61, .if_khz = 6000, @@ -51,6 +59,10 @@ static struct mxl5007t_config mxl5007t_hvr950q_config = { .if_freq_hz = MxL_IF_6_MHZ, }; +static struct tda18271_config hauppauge_woodbury_tunerconfig = { + .gate = TDA18271_GATE_DIGITAL, +}; + /*-------------------------------------------------------------------*/ static void urb_completion(struct urb *purb) { @@ -357,6 +369,15 @@ int au0828_dvb_register(struct au0828_dev *dev) &dev->i2c_adap, 0x60, &mxl5007t_hvr950q_config); break; + case AU0828_BOARD_HAUPPAUGE_WOODBURY: + dvb->frontend = dvb_attach(au8522_attach, + &hauppauge_woodbury_config, + &dev->i2c_adap); + if (dvb->frontend != NULL) + dvb_attach(tda18271_attach, dvb->frontend, + 0x60, &dev->i2c_adap, + &hauppauge_woodbury_tunerconfig); + break; default: printk(KERN_WARNING "The frontend of your DVB/ATSC card " "isn't supported yet\n"); -- cgit v0.10.2 From df76de098de0118cdcf6ec0e60cb4063837f8def Mon Sep 17 00:00:00 2001 From: Michael Krufky Date: Wed, 3 Sep 2008 16:46:40 -0300 Subject: V4L/DVB (8598): au8522: clean up function au8522_set_if re-write this function to make it simpler Signed-off-by: Michael Krufky Signed-off-by: Mauro Carvalho Chehab diff --git a/drivers/media/dvb/frontends/au8522.c b/drivers/media/dvb/frontends/au8522.c index 5741bc9..92c8fbe 100644 --- a/drivers/media/dvb/frontends/au8522.c +++ b/drivers/media/dvb/frontends/au8522.c @@ -304,67 +304,40 @@ static int au8522_mse2snr_lookup(struct mse2snr_tab *tab, int sz, int mse, return ret; } -/* 3.25 MHz IF Frequency table */ -static struct { - u16 reg; - u16 data; -} if_3_25_mhz_tab[] = { - { 0x80b5, 0x00 }, - { 0x80b6, 0x3d }, - { 0x80b7, 0xa0 }, -}; - -/* 4.00 MHz IF Frequency table */ -static struct { - u16 reg; - u16 data; -} if_4_mhz_tab[] = { - { 0x80b5, 0x00 }, - { 0x80b6, 0x4b }, - { 0x80b7, 0xd9 }, -}; - -/* 6.00 MHz IF Frequency table */ -static struct { - u16 reg; - u16 data; -} if_6_mhz_tab[] = { - { 0x80b5, 0xfb }, - { 0x80b6, 0x8e }, - { 0x80b7, 0x39 }, -}; - static int au8522_set_if(struct dvb_frontend *fe, enum au8522_if_freq if_freq) { struct au8522_state *state = fe->demodulator_priv; - int i; + u8 r0b5, r0b6, r0b7; + char *ifmhz; switch (if_freq) { case AU8522_IF_3_25MHZ: - dprintk("%s() 3.25 MHz\n", __func__); - for (i = 0; i < ARRAY_SIZE(if_3_25_mhz_tab); i++) - au8522_writereg(state, - if_3_25_mhz_tab[i].reg, - if_3_25_mhz_tab[i].data); + ifmhz = "3.25"; + r0b5 = 0x00; + r0b6 = 0x3d; + r0b7 = 0xa0; break; case AU8522_IF_4MHZ: - dprintk("%s() 4.00 MHz\n", __func__); - for (i = 0; i < ARRAY_SIZE(if_4_mhz_tab); i++) - au8522_writereg(state, - if_4_mhz_tab[i].reg, - if_4_mhz_tab[i].data); + ifmhz = "4.00"; + r0b5 = 0x00; + r0b6 = 0x4b; + r0b7 = 0xd9; break; case AU8522_IF_6MHZ: - dprintk("%s() 6.00 MHz\n", __func__); - for (i = 0; i < ARRAY_SIZE(if_6_mhz_tab); i++) - au8522_writereg(state, - if_6_mhz_tab[i].reg, - if_6_mhz_tab[i].data); + ifmhz = "6.00"; + r0b5 = 0xfb; + r0b6 = 0x8e; + r0b7 = 0x39; break; default: dprintk("%s() IF Frequency not supported\n", __func__); return -EINVAL; } + dprintk("%s() %s MHz\n", __func__, ifmhz); + au8522_writereg(state, 0x80b5, r0b5); + au8522_writereg(state, 0x80b6, r0b6); + au8522_writereg(state, 0x80b7, r0b7); + return 0; } -- cgit v0.10.2 From 3e3e2a8f1f6837a4f29b1416db40c88d846ab066 Mon Sep 17 00:00:00 2001 From: Michael Krufky Date: Wed, 3 Sep 2008 16:46:41 -0300 Subject: V4L/DVB (8599): au8522: remove if frequency settings from vsb/qam modulation tables Since IF frequency is set after the vsb/qam modulation tables are written, remove the redundant register settings from the vsb/qam modulation tables. Signed-off-by: Michael Krufky Signed-off-by: Mauro Carvalho Chehab diff --git a/drivers/media/dvb/frontends/au8522.c b/drivers/media/dvb/frontends/au8522.c index 92c8fbe..5a6cbb4 100644 --- a/drivers/media/dvb/frontends/au8522.c +++ b/drivers/media/dvb/frontends/au8522.c @@ -371,9 +371,6 @@ static struct { { 0x80af, 0x66 }, { 0x821b, 0xcc }, { 0x821d, 0x80 }, - { 0x80b5, 0xfb }, - { 0x80b6, 0x8e }, - { 0x80b7, 0x39 }, { 0x80a4, 0xe8 }, { 0x8231, 0x13 }, }; @@ -387,9 +384,6 @@ static struct { { 0x80a4, 0x00 }, { 0x8081, 0xc4 }, { 0x80a5, 0x40 }, - { 0x80b5, 0xfb }, - { 0x80b6, 0x8e }, - { 0x80b7, 0x39 }, { 0x80aa, 0x77 }, { 0x80ad, 0x77 }, { 0x80a6, 0x67 }, -- cgit v0.10.2 From e908b6e34c1b799c830cae5f8e721f80534f9748 Mon Sep 17 00:00:00 2001 From: Michael Krufky Date: Wed, 3 Sep 2008 16:46:43 -0300 Subject: V4L/DVB (8600): au0828: explicitly set 6 MHz IF frequency in hauppauge_hvr950q_config Explicitly set 6 MHz IF frequency for VSB and QAM in hauppauge_hvr950q_config. The default value is 6 MHz, so this patch doesn't change anything -- this only improves code readability and may prevent future bugs. Signed-off-by: Michael Krufky Signed-off-by: Mauro Carvalho Chehab diff --git a/drivers/media/video/au0828/au0828-dvb.c b/drivers/media/video/au0828/au0828-dvb.c index c862f9e..1948653 100644 --- a/drivers/media/video/au0828/au0828-dvb.c +++ b/drivers/media/video/au0828/au0828-dvb.c @@ -39,6 +39,8 @@ DVB_DEFINE_MOD_OPT_ADAPTER_NR(adapter_nr); static struct au8522_config hauppauge_hvr950q_config = { .demod_address = 0x8e >> 1, .status_mode = AU8522_DEMODLOCKING, + .qam_if = AU8522_IF_6MHZ, + .vsb_if = AU8522_IF_6MHZ, }; static struct au8522_config hauppauge_woodbury_config = { -- cgit v0.10.2 From 888fe747b5d134e2f3b5c2d3ecc25e1c6dcad4c3 Mon Sep 17 00:00:00 2001 From: Hans Verkuil Date: Wed, 3 Sep 2008 16:46:50 -0300 Subject: V4L/DVB (8629): v4l2-ioctl: do not try to handle private V4L1 ioctls Some drivers (e.g. zoran) have private V4L1 ioctls. Do not try to pass them to v4l1_compat_translate because then the driver will never see them. Signed-off-by: Hans Verkuil Signed-off-by: Mauro Carvalho Chehab diff --git a/drivers/media/video/v4l2-ioctl.c b/drivers/media/video/v4l2-ioctl.c index fdfe773..88c0465 100644 --- a/drivers/media/video/v4l2-ioctl.c +++ b/drivers/media/video/v4l2-ioctl.c @@ -674,7 +674,7 @@ static int __video_do_ioctl(struct inode *inode, struct file *file, __video_do_ioctl will be called again, with one or more V4L2 ioctls. ********************************************************/ - if (_IOC_TYPE(cmd) == 'v') + if (_IOC_TYPE(cmd) == 'v' && _IOC_NR(cmd) < BASE_VIDIOCPRIVATE) return v4l_compat_translate_ioctl(inode, file, cmd, arg, __video_do_ioctl); #endif -- cgit v0.10.2 From c58dc0beaf70bce4d04ff53b82a7035a255a04e4 Mon Sep 17 00:00:00 2001 From: Hans Verkuil Date: Wed, 3 Sep 2008 16:46:58 -0300 Subject: V4L/DVB (8633): ivtv: update ivtv version number Since for 2.6.27 ivtvfb uses DMA for write it is important that you can identify which ivtv version supports this and which doesn't. Increase the version number so we can tell the difference. Thanks to Ian Armstrong for pointing this out to me. Signed-off-by: Hans Verkuil Signed-off-by: Mauro Carvalho Chehab diff --git a/drivers/media/video/ivtv/ivtv-version.h b/drivers/media/video/ivtv/ivtv-version.h index 442f43f..8cd753d 100644 --- a/drivers/media/video/ivtv/ivtv-version.h +++ b/drivers/media/video/ivtv/ivtv-version.h @@ -22,7 +22,7 @@ #define IVTV_DRIVER_NAME "ivtv" #define IVTV_DRIVER_VERSION_MAJOR 1 -#define IVTV_DRIVER_VERSION_MINOR 3 +#define IVTV_DRIVER_VERSION_MINOR 4 #define IVTV_DRIVER_VERSION_PATCHLEVEL 0 #define IVTV_VERSION __stringify(IVTV_DRIVER_VERSION_MAJOR) "." __stringify(IVTV_DRIVER_VERSION_MINOR) "." __stringify(IVTV_DRIVER_VERSION_PATCHLEVEL) -- cgit v0.10.2 From d526afe06b285006c63ed8f2eba9589f04e3283a Mon Sep 17 00:00:00 2001 From: Hans Verkuil Date: Wed, 3 Sep 2008 16:47:14 -0300 Subject: V4L/DVB (8648): ivtv: improve CC support - change the work-queue to a single threaded high prio workqueue - use DMA instead of PIO for the sliced VBI data. - remove some incorrect tests - increase the internal VBI capture queue size for sliced VBI packets - ignore duplicate VBI lines With these changes it should finally be possible to get reliable closed captions. Signed-off-by: Hans Verkuil Signed-off-by: Mauro Carvalho Chehab diff --git a/drivers/media/video/ivtv/ivtv-driver.c b/drivers/media/video/ivtv/ivtv-driver.c index aea1664..4afc7ea 100644 --- a/drivers/media/video/ivtv/ivtv-driver.c +++ b/drivers/media/video/ivtv/ivtv-driver.c @@ -688,7 +688,7 @@ static int __devinit ivtv_init_struct1(struct ivtv *itv) spin_lock_init(&itv->lock); spin_lock_init(&itv->dma_reg_lock); - itv->irq_work_queues = create_workqueue(itv->name); + itv->irq_work_queues = create_singlethread_workqueue(itv->name); if (itv->irq_work_queues == NULL) { IVTV_ERR("Could not create ivtv workqueue\n"); return -1; diff --git a/drivers/media/video/ivtv/ivtv-driver.h b/drivers/media/video/ivtv/ivtv-driver.h index ab287b4..2ceb522 100644 --- a/drivers/media/video/ivtv/ivtv-driver.h +++ b/drivers/media/video/ivtv/ivtv-driver.h @@ -251,6 +251,7 @@ struct ivtv_mailbox_data { #define IVTV_F_I_DEC_PAUSED 20 /* the decoder is paused */ #define IVTV_F_I_INITED 21 /* set after first open */ #define IVTV_F_I_FAILED 22 /* set if first open failed */ +#define IVTV_F_I_WORK_INITED 23 /* worker thread was initialized */ /* Event notifications */ #define IVTV_F_I_EV_DEC_STOPPED 28 /* decoder stopped event */ diff --git a/drivers/media/video/ivtv/ivtv-irq.c b/drivers/media/video/ivtv/ivtv-irq.c index fba150a..34f3ab8 100644 --- a/drivers/media/video/ivtv/ivtv-irq.c +++ b/drivers/media/video/ivtv/ivtv-irq.c @@ -76,6 +76,13 @@ void ivtv_irq_work_handler(struct work_struct *work) DEFINE_WAIT(wait); + if (test_and_clear_bit(IVTV_F_I_WORK_INITED, &itv->i_flags)) { + struct sched_param param = { .sched_priority = 99 }; + + /* This thread must use the FIFO scheduler as it + is realtime sensitive. */ + sched_setscheduler(current, SCHED_FIFO, ¶m); + } if (test_and_clear_bit(IVTV_F_I_WORK_HANDLER_PIO, &itv->i_flags)) ivtv_pio_work_handler(itv); @@ -678,34 +685,14 @@ static void ivtv_irq_enc_start_cap(struct ivtv *itv) static void ivtv_irq_enc_vbi_cap(struct ivtv *itv) { - struct ivtv_stream *s_mpg = &itv->streams[IVTV_ENC_STREAM_TYPE_MPG]; u32 data[CX2341X_MBOX_MAX_DATA]; struct ivtv_stream *s; IVTV_DEBUG_HI_IRQ("ENC START VBI CAP\n"); s = &itv->streams[IVTV_ENC_STREAM_TYPE_VBI]; - /* If more than two VBI buffers are pending, then - clear the old ones and start with this new one. - This can happen during transition stages when MPEG capturing is - started, but the first interrupts haven't arrived yet. During - that period VBI requests can accumulate without being able to - DMA the data. Since at most four VBI DMA buffers are available, - we just drop the old requests when there are already three - requests queued. */ - if (s->sg_pending_size > 2) { - struct ivtv_buffer *buf; - list_for_each_entry(buf, &s->q_predma.list, list) - ivtv_buf_sync_for_cpu(s, buf); - ivtv_queue_move(s, &s->q_predma, NULL, &s->q_free, 0); - s->sg_pending_size = 0; - } - /* if we can append the data, and the MPEG stream isn't capturing, - then start a DMA request for just the VBI data. */ - if (!stream_enc_dma_append(s, data) && - !test_bit(IVTV_F_S_STREAMING, &s_mpg->s_flags)) { + if (!stream_enc_dma_append(s, data)) set_bit(ivtv_use_pio(s) ? IVTV_F_S_PIO_PENDING : IVTV_F_S_DMA_PENDING, &s->s_flags); - } } static void ivtv_irq_dec_vbi_reinsert(struct ivtv *itv) diff --git a/drivers/media/video/ivtv/ivtv-queue.h b/drivers/media/video/ivtv/ivtv-queue.h index 7cfc0c9..476556a 100644 --- a/drivers/media/video/ivtv/ivtv-queue.h +++ b/drivers/media/video/ivtv/ivtv-queue.h @@ -23,7 +23,7 @@ #define IVTV_QUEUE_H #define IVTV_DMA_UNMAPPED ((u32) -1) -#define SLICED_VBI_PIO 1 +#define SLICED_VBI_PIO 0 /* ivtv_buffer utility functions */ diff --git a/drivers/media/video/ivtv/ivtv-streams.c b/drivers/media/video/ivtv/ivtv-streams.c index 54d2023..730e85d 100644 --- a/drivers/media/video/ivtv/ivtv-streams.c +++ b/drivers/media/video/ivtv/ivtv-streams.c @@ -363,7 +363,7 @@ static void ivtv_vbi_setup(struct ivtv *itv) /* Every X number of frames a VBI interrupt arrives (frames as in 25 or 30 fps) */ data[1] = 1; /* The VBI frames are stored in a ringbuffer with this size (with a VBI frame as unit) */ - data[2] = raw ? 4 : 8; + data[2] = raw ? 4 : 4 * (itv->vbi.raw_size / itv->vbi.enc_size); /* The start/stop codes determine which VBI lines end up in the raw VBI data area. The codes are from table 24 in the saa7115 datasheet. Each raw/sliced/video line is framed with codes FF0000XX where XX is the SAV/EAV (Start/End of Active Video) diff --git a/drivers/media/video/ivtv/ivtv-vbi.c b/drivers/media/video/ivtv/ivtv-vbi.c index 71798f0..1ce9deb 100644 --- a/drivers/media/video/ivtv/ivtv-vbi.c +++ b/drivers/media/video/ivtv/ivtv-vbi.c @@ -293,6 +293,7 @@ static u32 compress_sliced_buf(struct ivtv *itv, u32 line, u8 *buf, u32 size, u8 u32 line_size = itv->vbi.sliced_decoder_line_size; struct v4l2_decode_vbi_line vbi; int i; + unsigned lines = 0; /* find the first valid line */ for (i = 0; i < size; i++, buf++) { @@ -313,7 +314,8 @@ static u32 compress_sliced_buf(struct ivtv *itv, u32 line, u8 *buf, u32 size, u8 } vbi.p = p + 4; itv->video_dec_func(itv, VIDIOC_INT_DECODE_VBI_LINE, &vbi); - if (vbi.type) { + if (vbi.type && !(lines & (1 << vbi.line))) { + lines |= 1 << vbi.line; itv->vbi.sliced_data[line].id = vbi.type; itv->vbi.sliced_data[line].field = vbi.is_second_field; itv->vbi.sliced_data[line].line = vbi.line; -- cgit v0.10.2 From e52a5574de9d3bb297a26566871eabcbdfab13b5 Mon Sep 17 00:00:00 2001 From: Jean-Francois Moine Date: Wed, 3 Sep 2008 16:47:21 -0300 Subject: V4L/DVB (8660): gspca: Simplify the scan of URB packets in pac7311. Signed-off-by: Jean-Francois Moine Signed-off-by: Mauro Carvalho Chehab diff --git a/drivers/media/video/gspca/pac7311.c b/drivers/media/video/gspca/pac7311.c index 815bea6..caa3329 100644 --- a/drivers/media/video/gspca/pac7311.c +++ b/drivers/media/video/gspca/pac7311.c @@ -40,7 +40,8 @@ struct sd { unsigned char colors; unsigned char autogain; - char ffseq; + char ffnb; /* number of 'ff' in the previous frame */ + char tosof; /* number of bytes before next start of frame */ signed char ag_cnt; #define AG_CNT_START 13 }; @@ -335,6 +336,10 @@ static int sd_open(struct gspca_dev *gspca_dev) static void sd_start(struct gspca_dev *gspca_dev) { + struct sd *sd = (struct sd *) gspca_dev; + + sd->ffnb = 0; + sd->tosof = 0; reg_w(gspca_dev, 0xff, 0x01); reg_w_buf(gspca_dev, 0x0002, "\x48\x0a\x40\x08\x00\x00\x08\x00", 8); reg_w_buf(gspca_dev, 0x000a, "\x06\xff\x11\xff\x5a\x30\x90\x4c", 8); @@ -511,114 +516,123 @@ static void do_autogain(struct gspca_dev *gspca_dev) } } +/* output the jpeg header */ +static void put_jpeg_head(struct gspca_dev *gspca_dev, + struct gspca_frame *frame) +{ + unsigned char tmpbuf[4]; + + gspca_frame_add(gspca_dev, FIRST_PACKET, frame, + (__u8 *) pac7311_jpeg_header, + 12); + tmpbuf[0] = gspca_dev->height >> 8; + tmpbuf[1] = gspca_dev->height & 0xff; + tmpbuf[2] = gspca_dev->width >> 8; + tmpbuf[3] = gspca_dev->width & 0xff; + gspca_frame_add(gspca_dev, INTER_PACKET, frame, + tmpbuf, 4); + gspca_frame_add(gspca_dev, INTER_PACKET, frame, + (__u8 *) &pac7311_jpeg_header[16], + PAC7311_JPEG_HEADER_SIZE - 16); +} + +/* this function is run at interrupt level */ static void sd_pkt_scan(struct gspca_dev *gspca_dev, struct gspca_frame *frame, /* target */ __u8 *data, /* isoc packet */ int len) /* iso packet length */ { struct sd *sd = (struct sd *) gspca_dev; - unsigned char tmpbuf[4]; - int i, p, ffseq; - -/* if (len < 5) { */ - if (len < 6) { -/* gspca_dev->last_packet_type = DISCARD_PACKET; */ - return; - } - - ffseq = sd->ffseq; - - for (p = 0; p < len - 6; p++) { - if ((data[0 + p] == 0xff) - && (data[1 + p] == 0xff) - && (data[2 + p] == 0x00) - && (data[3 + p] == 0xff) - && (data[4 + p] == 0x96)) { - - /* start of frame */ - if (sd->ag_cnt >= 0 && p > 28) { - sd->lum_sum += data[p - 23]; - if (--sd->ag_cnt < 0) { - sd->ag_cnt = AG_CNT_START; - atomic_set(&sd->avg_lum, - sd->lum_sum / AG_CNT_START); - sd->lum_sum = 0; - atomic_set(&sd->do_gain, 1); + int i; + +#define INTER_FRAME 0x53 +#define LUM_OFFSET 0x1e /* reverse offset / start of frame */ + + /* + * inside a frame, there may be: + * escaped ff ('ff 00') + * sequences'ff ff ff xx' to remove + * end of frame ('ff d9') + * at the end of frame, there are: + * ff d9 end of frame + * 0x33 bytes + * one byte luminosity + * 0x16 bytes + * ff ff 00 ff 96 62 44 start of frame header + */ + + if (sd->tosof == 0) { /* if inside a frame */ + + /* check for 'ff ff ff xx' at start and at end of packet */ + /* (len is always >= 3) */ + switch (sd->ffnb) { + case 1: + if (data[0] != 0xff) + break; /* keep 'ff 00' */ + /* fall thru */ + case 2: + case 3: + data += 4 - sd->ffnb; + len -= 4 - sd->ffnb; + sd->ffnb = 0; + break; + } + if (data[len - 1] == 0xff) { + if (data[len - 2] == 0xff) { + if (data[len - 3] == 0xff) { + sd->ffnb = 3; + len -= 3; + } else { + sd->ffnb = 2; + len -= 2; } + } else { + sd->ffnb = 1; + len--; } - - /* copy the end of data to the current frame */ - frame = gspca_frame_add(gspca_dev, LAST_PACKET, frame, - data, p); - - /* put the JPEG header in the new frame */ - gspca_frame_add(gspca_dev, FIRST_PACKET, frame, - (unsigned char *) pac7311_jpeg_header, - 12); - tmpbuf[0] = gspca_dev->height >> 8; - tmpbuf[1] = gspca_dev->height & 0xff; - tmpbuf[2] = gspca_dev->width >> 8; - tmpbuf[3] = gspca_dev->width & 0xff; - gspca_frame_add(gspca_dev, INTER_PACKET, frame, - tmpbuf, 4); - gspca_frame_add(gspca_dev, INTER_PACKET, frame, - (unsigned char *) &pac7311_jpeg_header[16], - PAC7311_JPEG_HEADER_SIZE - 16); - - data += p + 7; - len -= p + 7; - ffseq = 0; - break; } + } else { /* outside a frame */ + + /* + * get the luminosity + * and go to the start of frame + */ + data += sd->tosof; + len -= sd->tosof; + if (sd->tosof > LUM_OFFSET) + sd->lum_sum += data[-LUM_OFFSET]; + put_jpeg_head(gspca_dev, frame); + sd->tosof = 0; } - /* remove the 'ff ff ff xx' sequences */ - switch (ffseq) { - case 3: - data += 1; - len -= 1; - break; - case 2: - if (data[0] == 0xff) { - data += 2; - len -= 2; - frame->data_end -= 2; - } - break; - case 1: - if (data[0] == 0xff - && data[1] == 0xff) { - data += 3; - len -= 3; - frame->data_end -= 1; - } - break; - } - for (i = 0; i < len - 4; i++) { - if (data[i] == 0xff - && data[i + 1] == 0xff - && data[i + 2] == 0xff) { - memmove(&data[i], &data[i + 4], len - i - 4); - len -= 4; + for (i = 0; i < len; i++) { + if (data[i] != 0xff) + continue; + switch (data[i + 1]) { + case 0xd9: /* end of frame */ + frame = gspca_frame_add(gspca_dev, + LAST_PACKET, + frame, data, i + 1); + data += INTER_FRAME; + len -= INTER_FRAME; + i = 0; + if (len > LUM_OFFSET) + sd->lum_sum += data[-LUM_OFFSET]; + if (len < 0) { + sd->tosof = -len; + break; + } + put_jpeg_head(gspca_dev, frame); + break; + case 0xff: /* 'ff ff ff xx' */ + gspca_frame_add(gspca_dev, INTER_PACKET, + frame, data, i); + data += i + 4; + len -= i + 4; + i = 0; + break; } } - ffseq = 0; - if (data[len - 4] == 0xff) { - if (data[len - 3] == 0xff - && data[len - 2] == 0xff) { - len -= 4; - } - } else if (data[len - 3] == 0xff) { - if (data[len - 2] == 0xff - && data[len - 1] == 0xff) - ffseq = 3; - } else if (data[len - 2] == 0xff) { - if (data[len - 1] == 0xff) - ffseq = 2; - } else if (data[len - 1] == 0xff) - ffseq = 1; - sd->ffseq = ffseq; - gspca_frame_add(gspca_dev, INTER_PACKET, frame, data, len); } static void getbrightness(struct gspca_dev *gspca_dev) -- cgit v0.10.2 From 23d9e4776b426d1f8a602e0e8d868154847f0dd4 Mon Sep 17 00:00:00 2001 From: Jean-Francois Moine Date: Wed, 3 Sep 2008 16:47:22 -0300 Subject: V4L/DVB (8661): gspca: Bug in the previous changeset about pac7311. Signed-off-by: Jean-Francois Moine Signed-off-by: Mauro Carvalho Chehab diff --git a/drivers/media/video/gspca/pac7311.c b/drivers/media/video/gspca/pac7311.c index caa3329..96cd7f6 100644 --- a/drivers/media/video/gspca/pac7311.c +++ b/drivers/media/video/gspca/pac7311.c @@ -610,13 +610,14 @@ static void sd_pkt_scan(struct gspca_dev *gspca_dev, continue; switch (data[i + 1]) { case 0xd9: /* end of frame */ + i += 2; frame = gspca_frame_add(gspca_dev, LAST_PACKET, - frame, data, i + 1); - data += INTER_FRAME; - len -= INTER_FRAME; + frame, data, i); + data += i + INTER_FRAME; + len -= i + INTER_FRAME; i = 0; - if (len > LUM_OFFSET) + if (len > -LUM_OFFSET) sd->lum_sum += data[-LUM_OFFSET]; if (len < 0) { sd->tosof = -len; -- cgit v0.10.2 From d2d16e9084ee44088974c3312b803d54dd9b46d7 Mon Sep 17 00:00:00 2001 From: Jean-Francois Moine Date: Wed, 3 Sep 2008 16:47:23 -0300 Subject: V4L/DVB (8663): gspca: Webcam 0c45:6128 added in sonixj. Patch adapted from a patch to gspcav1 made by the google microdia group. Signed-off-by: Jean-Francois Moine Signed-off-by: Mauro Carvalho Chehab diff --git a/Documentation/video4linux/gspca.txt b/Documentation/video4linux/gspca.txt index 78a863a..c7fc9fa 100644 --- a/Documentation/video4linux/gspca.txt +++ b/Documentation/video4linux/gspca.txt @@ -220,6 +220,7 @@ sonixj 0c45:60c0 Sangha Sn535 sonixj 0c45:60ec SN9C105+MO4000 sonixj 0c45:60fb Surfer NoName sonixj 0c45:60fc LG-LIC300 +sonixj 0c45:6128 Microdia/Sonix SNP325 sonixj 0c45:612a Avant Camera sonixj 0c45:612c Typhoon Rasy Cam 1.3MPix sonixj 0c45:6130 Sonix Pccam diff --git a/drivers/media/video/gspca/sonixj.c b/drivers/media/video/gspca/sonixj.c index 245a30e..151e1b6 100644 --- a/drivers/media/video/gspca/sonixj.c +++ b/drivers/media/video/gspca/sonixj.c @@ -54,8 +54,9 @@ struct sd { #define SENSOR_HV7131R 0 #define SENSOR_MI0360 1 #define SENSOR_MO4000 2 -#define SENSOR_OV7648 3 -#define SENSOR_OV7660 4 +#define SENSOR_OM6802 3 +#define SENSOR_OV7648 4 +#define SENSOR_OV7660 5 unsigned char i2c_base; }; @@ -180,6 +181,20 @@ static const __u8 sn_mo4000[] = { 0x08, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00 }; +static const __u8 sn_om6802[] = { +/* reg0 reg1 reg2 reg3 reg4 reg5 reg6 reg7 */ + 0x00, 0x23, 0x72, 0x00, 0x1a, 0x34, 0x27, 0x20, +/* reg8 reg9 rega regb regc regd rege regf */ + 0x80, 0x34, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, +/* reg10 reg11 reg12 reg13 reg14 reg15 reg16 reg17 */ + 0x03, 0x00, 0x51, 0x01, 0x00, 0x28, 0x1e, 0x40, +/* reg18 reg19 reg1a reg1b reg1c reg1d reg1e reg1f */ + 0x05, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x08, 0x22, 0x44, 0x63, 0x7d, 0x92, 0xa3, 0xaf, + 0xbc, 0xc4, 0xcd, 0xd5, 0xdc, 0xe1, 0xe8, 0xef, + 0xf7 +}; + static const __u8 sn_ov7648[] = { /* reg0 reg1 reg2 reg3 reg4 reg5 reg6 reg7 */ 0x00, 0x21, 0x62, 0x00, 0x1a, 0x20, 0x20, 0x20, @@ -207,6 +222,7 @@ static const __u8 *sn_tb[] = { sn_hv7131, sn_mi0360, sn_mo4000, + sn_om6802, sn_ov7648, sn_ov7660 }; @@ -340,6 +356,40 @@ static const __u8 mo4000_sensor_init[][8] = { {0xa1, 0x21, 0x11, 0x38, 0x00, 0x00, 0x00, 0x10}, {} }; +static __u8 om6802_sensor_init[][8] = { + {0xa0, 0x34, 0x90, 0x05, 0x00, 0x00, 0x00, 0x10}, + {0xa0, 0x34, 0x49, 0x85, 0x00, 0x00, 0x00, 0x10}, + {0xa0, 0x34, 0x5a, 0xc0, 0x00, 0x00, 0x00, 0x10}, + {0xa0, 0x34, 0xdd, 0x18, 0x00, 0x00, 0x00, 0x10}, +/* {0xa0, 0x34, 0xfb, 0x11, 0x00, 0x00, 0x00, 0x10}, */ + {0xa0, 0x34, 0xf0, 0x04, 0x00, 0x00, 0x00, 0x10}, + /* white balance & auto-exposure */ +/* {0xa0, 0x34, 0xf1, 0x02, 0x00, 0x00, 0x00, 0x10}, + * set color mode */ +/* {0xa0, 0x34, 0xfe, 0x5b, 0x00, 0x00, 0x00, 0x10}, + * max AGC value in AE */ +/* {0xa0, 0x34, 0xe5, 0x00, 0x00, 0x00, 0x00, 0x10}, + * preset AGC */ +/* {0xa0, 0x34, 0xe6, 0x00, 0x00, 0x00, 0x00, 0x10}, + * preset brightness */ +/* {0xa0, 0x34, 0xe7, 0x00, 0x00, 0x00, 0x00, 0x10}, + * preset contrast */ +/* {0xa0, 0x34, 0xe8, 0x31, 0x00, 0x00, 0x00, 0x10}, + * preset gamma */ + {0xa0, 0x34, 0xe9, 0x0f, 0x00, 0x00, 0x00, 0x10}, + /* luminance mode (0x4f = AE) */ + {0xa0, 0x34, 0xe4, 0xff, 0x00, 0x00, 0x00, 0x10}, + /* preset shutter */ +/* {0xa0, 0x34, 0xef, 0x00, 0x00, 0x00, 0x00, 0x10}, + * auto frame rate */ +/* {0xa0, 0x34, 0xfb, 0xee, 0x00, 0x00, 0x00, 0x10}, */ + +/* {0xa0, 0x34, 0x71, 0x84, 0x00, 0x00, 0x00, 0x10}, */ +/* {0xa0, 0x34, 0x72, 0x05, 0x00, 0x00, 0x00, 0x10}, */ +/* {0xa0, 0x34, 0x68, 0x80, 0x00, 0x00, 0x00, 0x10}, */ +/* {0xa0, 0x34, 0x69, 0x01, 0x00, 0x00, 0x00, 0x10}, */ + {} +}; static const __u8 ov7660_sensor_init[][8] = { {0xa1, 0x21, 0x12, 0x80, 0x00, 0x00, 0x00, 0x10}, /* reset SCCB */ /* (delay 20ms) */ @@ -685,8 +735,14 @@ static int configure_gpio(struct gspca_dev *gspca_dev, reg_w(gspca_dev, 0x03, &sn9c1xx[3], 0x0f); - switch (sd->bridge) { - case BRIDGE_SN9C325: + switch (sd->sensor) { + case SENSOR_OM6802: + reg_w1(gspca_dev, 0x02, 0x71); + reg_w1(gspca_dev, 0x01, 0x42); + reg_w1(gspca_dev, 0x17, 0x64); + reg_w1(gspca_dev, 0x01, 0x42); + break; + case SENSOR_OV7648: reg_w1(gspca_dev, 0x01, 0x43); reg_w1(gspca_dev, 0x17, 0xae); reg_w1(gspca_dev, 0x01, 0x42); @@ -695,11 +751,11 @@ static int configure_gpio(struct gspca_dev *gspca_dev, reg_w1(gspca_dev, 0x01, 0x43); reg_w1(gspca_dev, 0x17, 0x61); reg_w1(gspca_dev, 0x01, 0x42); - } - - if (sd->sensor == SENSOR_HV7131R) { - if (probesensor(gspca_dev) < 0) - return -ENODEV; + if (sd->sensor == SENSOR_HV7131R) { + if (probesensor(gspca_dev) < 0) + return -ENODEV; + } + break; } return 0; } @@ -737,6 +793,16 @@ static void mo4000_InitSensor(struct gspca_dev *gspca_dev) } } +static void om6802_InitSensor(struct gspca_dev *gspca_dev) +{ + int i = 0; + + while (om6802_sensor_init[i][0]) { + i2c_w8(gspca_dev, om6802_sensor_init[i]); + i++; + } +} + static void ov7648_InitSensor(struct gspca_dev *gspca_dev) { int i = 0; @@ -891,6 +957,20 @@ static unsigned int setexposure(struct gspca_dev *gspca_dev, | ((expoMo10[3] & 0x30) >> 4)); break; } + case SENSOR_OM6802: { + __u8 gainOm[] = + { 0xa0, 0x34, 0xe5, 0x00, 0x00, 0x00, 0x00, 0x10 }; + + if (expo > 0x03ff) + expo = 0x03ff; + if (expo < 0x0001) + expo = 0x0001; + gainOm[3] = expo >> 2; + i2c_w8(gspca_dev, gainOm); + reg_w1(gspca_dev, 0x96, expo >> 5); + PDEBUG(D_CONF, "set exposure %d", gainOm[3]); + break; + } } return expo; } @@ -901,6 +981,7 @@ static void setbrightness(struct gspca_dev *gspca_dev) unsigned int expo; __u8 k2; + k2 = sd->brightness >> 10; switch (sd->sensor) { case SENSOR_HV7131R: expo = sd->brightness << 4; @@ -915,9 +996,13 @@ static void setbrightness(struct gspca_dev *gspca_dev) expo = sd->brightness >> 4; sd->exposure = setexposure(gspca_dev, expo); break; + case SENSOR_OM6802: + expo = sd->brightness >> 6; + sd->exposure = setexposure(gspca_dev, expo); + k2 = sd->brightness >> 11; + break; } - k2 = sd->brightness >> 10; reg_w1(gspca_dev, 0x96, k2); } @@ -1049,6 +1134,11 @@ static void sd_start(struct gspca_dev *gspca_dev) /* reg1 = 0x06; * 640 clk 24Mz (done) */ } break; + case SENSOR_OM6802: + om6802_InitSensor(gspca_dev); + reg1 = 0x46; /* 640 clk 24Mz */ + reg17 = 0x64; /* 640 MCKSIZE */ + break; case SENSOR_OV7648: ov7648_InitSensor(gspca_dev); reg17 = 0xa2; @@ -1174,6 +1264,7 @@ static void do_autogain(struct gspca_dev *gspca_dev) default: /* case SENSOR_MO4000: */ /* case SENSOR_MI0360: */ +/* case SENSOR_OM6802: */ expotimes = sd->exposure; expotimes += (luma_mean - delta) >> 6; if (expotimes < 0) @@ -1246,7 +1337,8 @@ static unsigned int getexposure(struct gspca_dev *gspca_dev) i2c_r5(gspca_dev, 0x09); return (gspca_dev->usb_buf[0] << 8) | gspca_dev->usb_buf[1]; - case SENSOR_MO4000: + default: +/* case SENSOR_MO4000: */ i2c_r5(gspca_dev, 0x0e); hexpo = 0; /* gspca_dev->usb_buf[1] & 0x07; */ mexpo = 0x40; /* gspca_dev->usb_buf[2] & 0xff; */ @@ -1254,7 +1346,8 @@ static unsigned int getexposure(struct gspca_dev *gspca_dev) PDEBUG(D_CONF, "exposure %d", (hexpo << 10) | (mexpo << 2) | lexpo); return (hexpo << 10) | (mexpo << 2) | lexpo; - default: +#if 0 +/*jfm: not called*/ /* case SENSOR_OV7648: * jfm: is it ok for 7648? */ /* case SENSOR_OV7660: */ /* read sensor exposure */ @@ -1264,7 +1357,9 @@ static unsigned int getexposure(struct gspca_dev *gspca_dev) i2c_r5(gspca_dev, 0x08); mexpo = gspca_dev->usb_buf[2]; return (hexpo << 10) | (mexpo << 2) | lexpo; +#endif } + /* not reached */ } static void getbrightness(struct gspca_dev *gspca_dev) @@ -1277,9 +1372,8 @@ static void getbrightness(struct gspca_dev *gspca_dev) sd->brightness = getexposure(gspca_dev) >> 4; break; case SENSOR_MI0360: - sd->brightness = getexposure(gspca_dev) << 4; - break; case SENSOR_MO4000: + case SENSOR_OM6802: sd->brightness = getexposure(gspca_dev) << 4; break; } @@ -1406,9 +1500,9 @@ static const __devinitdata struct usb_device_id device_table[] = { /* {USB_DEVICE(0x0c45, 0x6108), BSI(SN9C120, OM6801, 0x??)}, */ /* {USB_DEVICE(0x0c45, 0x6122), BSI(SN9C110, ICM105C, 0x??)}, */ /* {USB_DEVICE(0x0c45, 0x6123), BSI(SN9C110, SanyoCCD, 0x??)}, */ - {USB_DEVICE(0x0c45, 0x612a), BSI(SN9C325, OV7648, 0x21)}, -/* bw600.inf: - {USB_DEVICE(0x0c45, 0x612a), BSI(SN9C110, OV7648, 0x21)}, */ + {USB_DEVICE(0x0c45, 0x6128), BSI(SN9C110, OM6802, 0x21)}, /*sn9c325?*/ +/*bw600.inf:*/ + {USB_DEVICE(0x0c45, 0x612a), BSI(SN9C110, OV7648, 0x21)}, /*sn9c325?*/ {USB_DEVICE(0x0c45, 0x612c), BSI(SN9C110, MO4000, 0x21)}, /* {USB_DEVICE(0x0c45, 0x612e), BSI(SN9C110, OV7630, 0x??)}, */ /* {USB_DEVICE(0x0c45, 0x612f), BSI(SN9C110, ICM105C, 0x??)}, */ -- cgit v0.10.2 From 49b57dba2f6425e9b42874b4dec2433b335fa69c Mon Sep 17 00:00:00 2001 From: Jean-Francois Moine Date: Wed, 3 Sep 2008 16:47:25 -0300 Subject: V4L/DVB (8664): gspca: The bridge/sensor of the webcam 093a:2621 is a PAC 7302. Signed-off-by: Jean-Francois Moine Signed-off-by: Mauro Carvalho Chehab diff --git a/drivers/media/video/gspca/pac7311.c b/drivers/media/video/gspca/pac7311.c index 96cd7f6..034c00d 100644 --- a/drivers/media/video/gspca/pac7311.c +++ b/drivers/media/video/gspca/pac7311.c @@ -44,6 +44,10 @@ struct sd { char tosof; /* number of bytes before next start of frame */ signed char ag_cnt; #define AG_CNT_START 13 + + __u8 sensor; +#define SENSOR_PAC7302 0 +#define SENSOR_PAC7311 1 }; /* V4L2 controls supported by the driver */ @@ -206,9 +210,158 @@ static const __u8 pac7311_jpeg_header[] = { 0x11, 0x00, 0x3f, 0x00 }; +/* pac 7302 */ +static const __u8 probe_7302[] = { +/* index,value */ + 0xff, 0x01, /* page 1 */ + 0x78, 0x00, /* deactivate */ + 0xff, 0x01, + 0x78, 0x40, /* led off */ +}; +static const __u8 start_7302[] = { +/* index, len, [value]* */ + 0x00, 12, 0x01, 0x40, 0x40, 0x40, 0x01, 0xe0, 0x02, 0x80, + 0x00, 0x00, 0x00, 0x00, + 0x0d, 24, 0x03, 0x01, 0x00, 0xb5, 0x07, 0xcb, 0x00, 0x00, + 0x07, 0xc8, 0x00, 0xea, 0x07, 0xcf, 0x07, 0xf7, + 0x07, 0x7e, 0x01, 0x0b, 0x00, 0x00, 0x00, 0x11, + 0x26, 2, 0xaa, 0xaa, + 0x2e, 1, 0x31, + 0x38, 1, 0x01, + 0x3a, 3, 0x14, 0xff, 0x5a, + 0x43, 11, 0x00, 0x0a, 0x18, 0x11, 0x01, 0x2c, 0x88, 0x11, + 0x00, 0x54, 0x11, + 0x55, 1, 0x00, + 0x62, 4, 0x10, 0x1e, 0x1e, 0x18, + 0x6b, 1, 0x00, + 0x6e, 3, 0x08, 0x06, 0x00, + 0x72, 3, 0x00, 0xff, 0x00, + 0x7d, 23, 0x01, 0x01, 0x58, 0x46, 0x50, 0x3c, 0x50, 0x3c, + 0x54, 0x46, 0x54, 0x56, 0x52, 0x50, 0x52, 0x50, + 0x56, 0x64, 0xa4, 0x00, 0xda, 0x00, 0x00, + 0xa2, 10, 0x22, 0x2c, 0x3c, 0x54, 0x69, 0x7c, 0x9c, 0xb9, + 0xd2, 0xeb, + 0xaf, 1, 0x02, + 0xb5, 2, 0x08, 0x08, + 0xb8, 2, 0x08, 0x88, + 0xc4, 4, 0xae, 0x01, 0x04, 0x01, + 0xcc, 1, 0x00, + 0xd1, 11, 0x01, 0x30, 0x49, 0x5e, 0x6f, 0x7f, 0x8e, 0xa9, + 0xc1, 0xd7, 0xec, + 0xdc, 1, 0x01, + 0xff, 1, 0x01, + 0x12, 3, 0x02, 0x00, 0x01, + 0x3e, 2, 0x00, 0x00, + 0x76, 5, 0x01, 0x20, 0x40, 0x00, 0xf2, + 0x7c, 1, 0x00, + 0x7f, 10, 0x4b, 0x0f, 0x01, 0x2c, 0x02, 0x58, 0x03, 0x20, + 0x02, 0x00, + 0x96, 5, 0x01, 0x10, 0x04, 0x01, 0x04, + 0xc8, 17, 0x00, 0x00, 0x00, 0x00, 0x00, 0x07, 0x00, 0x00, + 0x07, 0x00, 0x01, 0x07, 0x04, 0x01, + 0x01, + 0xdb, 2, 0x00, 0x01, + 0xde, 8, 0x00, 0x01, 0x04, 0x04, 0x00, 0x00, 0x00, + 0xe6, 4, 0x00, 0x00, 0x00, 0x01, + 0xeb, 1, 0x00, + 0xff, 1, 0x02, + 0x22, 1, 0x00, + 0xff, 1, 0x03, + 0x00, 255, /* load the page 3 */ + 0x11, 1, 0x01, + 0xff, 1, 0x02, + 0x13, 1, 0x00, + 0x22, 4, 0x1f, 0xa4, 0xf0, 0x96, + 0x27, 2, 0x14, 0x0c, + 0x2a, 5, 0xc8, 0x00, 0x18, 0x12, 0x22, + 0x64, 8, 0x00, 0x00, 0xf0, 0x01, 0x14, 0x44, 0x44, 0x44, + 0x6e, 1, 0x08, + 0xff, 1, 0x03, + 0x78, 1, 0x00, + 0, 0 /* end of sequence */ +}; + +/* page 3 - the value 0xaa says skip the index - see reg_w_page() */ +static const __u8 page3_7302[] = { + 0x90, 0x40, 0x03, 0x50, 0xc2, 0x01, 0x14, 0x16, + 0x14, 0x12, 0x00, 0x00, 0x00, 0x02, 0x33, 0x00, + 0x0f, 0x01, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x47, 0x01, 0xb3, 0x01, 0x00, + 0x00, 0x08, 0x00, 0x00, 0x0d, 0x00, 0x00, 0x21, + 0x00, 0x00, 0x00, 0x54, 0xf4, 0x02, 0x52, 0x54, + 0xa4, 0xb8, 0xe0, 0x2a, 0xf6, 0x00, 0x00, 0x00, + 0x00, 0x1e, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0xfc, 0x00, 0xf2, 0x1f, 0x04, 0x00, 0x00, + 0x00, 0x00, 0x00, 0xc0, 0xc0, 0x10, 0x00, 0x00, + 0x00, 0x40, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x40, 0xff, 0x03, 0x19, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0xc8, 0xc8, 0xc8, + 0xc8, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x50, + 0x08, 0x10, 0x24, 0x40, 0x00, 0x00, 0x00, 0x00, + 0x01, 0x00, 0x02, 0x47, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x02, 0xfa, 0x00, 0x64, 0x5a, 0x28, 0x00, + 0x00 +}; + +/* pac 7311 */ +static const __u8 probe_7311[] = { + 0x78, 0x40, /* Bit_0=start stream, Bit_7=LED */ + 0x78, 0x40, /* Bit_0=start stream, Bit_7=LED */ + 0x78, 0x44, /* Bit_0=start stream, Bit_7=LED */ + 0xff, 0x04, + 0x27, 0x80, + 0x28, 0xca, + 0x29, 0x53, + 0x2a, 0x0e, + 0xff, 0x01, + 0x3e, 0x20, +}; + +static const __u8 start_7311[] = { +/* index, len, [value]* */ + 0xff, 1, 0x01, + 0x02, 53, 0x48, 0x0a, 0x40, 0x08, 0x00, 0x00, 0x08, 0x00, + 0x06, 0xff, 0x11, 0xff, 0x5a, 0x30, 0x90, 0x4c, + 0x00, 0x07, 0x00, 0x0a, 0x10, 0x00, 0xa0, 0x10, + 0x02, 0x00, 0x00, 0x00, 0x00, 0x0b, 0x01, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, + 0x3e, 52, 0x00, 0x00, 0x78, 0x52, 0x4a, 0x52, 0x78, 0x6e, + 0x48, 0x46, 0x48, 0x6e, 0x5f, 0x49, 0x42, 0x49, + 0x5f, 0x5f, 0x49, 0x42, 0x49, 0x5f, 0x6e, 0x48, + 0x46, 0x48, 0x6e, 0x78, 0x52, 0x4a, 0x52, 0x78, + 0x00, 0x00, 0x09, 0x1b, 0x34, 0x49, 0x5c, 0x9b, + 0xd0, 0xff, + 0x78, 6, 0x44, 0x00, 0xf2, 0x01, 0x01, 0x80, + 0x7f, 18, 0x2a, 0x1c, 0x00, 0xc8, 0x02, 0x58, 0x03, 0x84, + 0x12, 0x00, 0x1a, 0x04, 0x08, 0x0c, 0x10, 0x14, + 0x18, 0x20, + 0x96, 3, 0x01, 0x08, 0x04, + 0xa0, 4, 0x44, 0x44, 0x44, 0x04, + 0xf0, 13, 0x01, 0x00, 0x00, 0x00, 0x22, 0x00, 0x20, 0x00, + 0x3f, 0x00, 0x0a, 0x01, 0x00, + 0xff, 1, 0x04, + 0x00, 254, /* load the page 4 */ + 0x11, 1, 0x01, + 0, 0 /* end of sequence */ +}; + +/* page 4 - the value 0xaa says skip the index - see reg_w_page() */ +static const __u8 page4_7311[] = { + 0xaa, 0xaa, 0x04, 0x54, 0x07, 0x2b, 0x09, 0x0f, + 0x09, 0x00, 0xaa, 0xaa, 0x07, 0x00, 0x00, 0x62, + 0x08, 0xaa, 0x07, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x03, 0xa0, 0x01, 0xf4, 0xaa, + 0xaa, 0x00, 0x08, 0xaa, 0x03, 0xaa, 0x00, 0x01, + 0xca, 0x10, 0x06, 0x78, 0x00, 0x00, 0x00, 0x00, + 0x23, 0x28, 0x04, 0x11, 0x00, 0x00 +}; + static void reg_w_buf(struct gspca_dev *gspca_dev, - __u16 index, - const char *buffer, __u16 len) + __u8 index, + const char *buffer, int len) { memcpy(gspca_dev->usb_buf, buffer, len); usb_control_msg(gspca_dev->dev, @@ -221,7 +374,7 @@ static void reg_w_buf(struct gspca_dev *gspca_dev, } static __u8 reg_r(struct gspca_dev *gspca_dev, - __u16 index) + __u8 index) { usb_control_msg(gspca_dev->dev, usb_rcvctrlpipe(gspca_dev->dev, 0), @@ -234,7 +387,7 @@ static __u8 reg_r(struct gspca_dev *gspca_dev, } static void reg_w(struct gspca_dev *gspca_dev, - __u16 index, + __u8 index, __u8 value) { gspca_dev->usb_buf[0] = value; @@ -246,6 +399,74 @@ static void reg_w(struct gspca_dev *gspca_dev, 500); } +static void reg_w_seq(struct gspca_dev *gspca_dev, + const __u8 *seq, int len) +{ + while (--len >= 0) { + reg_w(gspca_dev, seq[0], seq[1]); + seq += 2; + } +} + +/* load the beginning of a page */ +static void reg_w_page(struct gspca_dev *gspca_dev, + const __u8 *page, int len) +{ + int index; + + for (index = 0; index < len; index++) { + if (page[index] == 0xaa) /* skip this index */ + continue; + gspca_dev->usb_buf[0] = page[index]; + usb_control_msg(gspca_dev->dev, + usb_sndctrlpipe(gspca_dev->dev, 0), + 0, /* request */ + USB_DIR_OUT | USB_TYPE_VENDOR | USB_RECIP_DEVICE, + 0, index, gspca_dev->usb_buf, 1, + 500); + } +} + +/* output a variable sequence */ +static void reg_w_var(struct gspca_dev *gspca_dev, + const __u8 *seq) +{ + int index, len; + + for (;;) { + index = *seq++; + len = *seq++; + switch (len) { + case 0: + return; + case 254: + reg_w_page(gspca_dev, page4_7311, sizeof page4_7311); + break; + case 255: + reg_w_page(gspca_dev, page3_7302, sizeof page3_7302); + break; + default: + if (len > 32) { + PDEBUG(D_ERR|D_STREAM, + "Incorrect variable sequence"); + return; + } + while (len > 0) { + if (len < 8) { + reg_w_buf(gspca_dev, index, seq, len); + seq += len; + break; + } + reg_w_buf(gspca_dev, index, seq, 8); + seq += 8; + index += 8; + len -= 8; + } + } + } + /* not reached */ +} + /* this function is called at probe time */ static int sd_config(struct gspca_dev *gspca_dev, const struct usb_device_id *id) @@ -253,22 +474,23 @@ static int sd_config(struct gspca_dev *gspca_dev, struct sd *sd = (struct sd *) gspca_dev; struct cam *cam; - PDEBUG(D_CONF, "Find Sensor PAC7311"); - reg_w(gspca_dev, 0x78, 0x40); /* Bit_0=start stream, Bit_7=LED */ - reg_w(gspca_dev, 0x78, 0x40); /* Bit_0=start stream, Bit_7=LED */ - reg_w(gspca_dev, 0x78, 0x44); /* Bit_0=start stream, Bit_7=LED */ - reg_w(gspca_dev, 0xff, 0x04); - reg_w(gspca_dev, 0x27, 0x80); - reg_w(gspca_dev, 0x28, 0xca); - reg_w(gspca_dev, 0x29, 0x53); - reg_w(gspca_dev, 0x2a, 0x0e); - reg_w(gspca_dev, 0xff, 0x01); - reg_w(gspca_dev, 0x3e, 0x20); - cam = &gspca_dev->cam; cam->epaddr = 0x05; - cam->cam_mode = vga_mode; - cam->nmodes = ARRAY_SIZE(vga_mode); + + sd->sensor = id->driver_info; + if (sd->sensor == SENSOR_PAC7302) { + PDEBUG(D_CONF, "Find Sensor PAC7302"); + reg_w_seq(gspca_dev, probe_7302, sizeof probe_7302); + + cam->cam_mode = &vga_mode[2]; /* only 640x480 */ + cam->nmodes = 1; + } else { + PDEBUG(D_CONF, "Find Sensor PAC7311"); + reg_w_seq(gspca_dev, probe_7302, sizeof probe_7302); + + cam->cam_mode = vga_mode; + cam->nmodes = ARRAY_SIZE(vga_mode); + } sd->brightness = BRIGHTNESS_DEF; sd->contrast = CONTRAST_DEF; @@ -283,10 +505,11 @@ static void setbrightness(struct gspca_dev *gspca_dev) struct sd *sd = (struct sd *) gspca_dev; int brightness; + if (sd->sensor == SENSOR_PAC7302) + return; /*jfm: inverted?*/ brightness = BRIGHTNESS_MAX - sd->brightness; reg_w(gspca_dev, 0xff, 0x04); -/* reg_w(gspca_dev, 0x0e, 0x00); */ reg_w(gspca_dev, 0x0f, brightness); /* load registers to sensor (Bit 0, auto clear) */ reg_w(gspca_dev, 0x11, 0x01); @@ -297,6 +520,8 @@ static void setcontrast(struct gspca_dev *gspca_dev) { struct sd *sd = (struct sd *) gspca_dev; + if (sd->sensor == SENSOR_PAC7302) + return; reg_w(gspca_dev, 0xff, 0x01); reg_w(gspca_dev, 0x80, sd->contrast); /* load registers to sensor (Bit 0, auto clear) */ @@ -308,6 +533,8 @@ static void setcolors(struct gspca_dev *gspca_dev) { struct sd *sd = (struct sd *) gspca_dev; + if (sd->sensor == SENSOR_PAC7302) + return; reg_w(gspca_dev, 0xff, 0x01); reg_w(gspca_dev, 0x10, sd->colors); /* load registers to sensor (Bit 0, auto clear) */ @@ -340,75 +567,12 @@ static void sd_start(struct gspca_dev *gspca_dev) sd->ffnb = 0; sd->tosof = 0; - reg_w(gspca_dev, 0xff, 0x01); - reg_w_buf(gspca_dev, 0x0002, "\x48\x0a\x40\x08\x00\x00\x08\x00", 8); - reg_w_buf(gspca_dev, 0x000a, "\x06\xff\x11\xff\x5a\x30\x90\x4c", 8); - reg_w_buf(gspca_dev, 0x0012, "\x00\x07\x00\x0a\x10\x00\xa0\x10", 8); - reg_w_buf(gspca_dev, 0x001a, "\x02\x00\x00\x00\x00\x0b\x01\x00", 8); - reg_w_buf(gspca_dev, 0x0022, "\x00\x00\x00\x00\x00\x00\x00\x00", 8); - reg_w_buf(gspca_dev, 0x002a, "\x00\x00\x00", 3); - reg_w_buf(gspca_dev, 0x003e, "\x00\x00\x78\x52\x4a\x52\x78\x6e", 8); - reg_w_buf(gspca_dev, 0x0046, "\x48\x46\x48\x6e\x5f\x49\x42\x49", 8); - reg_w_buf(gspca_dev, 0x004e, "\x5f\x5f\x49\x42\x49\x5f\x6e\x48", 8); - reg_w_buf(gspca_dev, 0x0056, "\x46\x48\x6e\x78\x52\x4a\x52\x78", 8); - reg_w_buf(gspca_dev, 0x005e, "\x00\x00\x09\x1b\x34\x49\x5c\x9b", 8); - reg_w_buf(gspca_dev, 0x0066, "\xd0\xff", 2); - reg_w_buf(gspca_dev, 0x0078, "\x44\x00\xf2\x01\x01\x80", 6); - reg_w_buf(gspca_dev, 0x007f, "\x2a\x1c\x00\xc8\x02\x58\x03\x84", 8); - reg_w_buf(gspca_dev, 0x0087, "\x12\x00\x1a\x04\x08\x0c\x10\x14", 8); - reg_w_buf(gspca_dev, 0x008f, "\x18\x20", 2); - reg_w_buf(gspca_dev, 0x0096, "\x01\x08\x04", 3); - reg_w_buf(gspca_dev, 0x00a0, "\x44\x44\x44\x04", 4); - reg_w_buf(gspca_dev, 0x00f0, "\x01\x00\x00\x00\x22\x00\x20\x00", 8); - reg_w_buf(gspca_dev, 0x00f8, "\x3f\x00\x0a\x01\x00", 5); - reg_w(gspca_dev, 0xff, 0x04); - reg_w(gspca_dev, 0x02, 0x04); - reg_w(gspca_dev, 0x03, 0x54); - reg_w(gspca_dev, 0x04, 0x07); - reg_w(gspca_dev, 0x05, 0x2b); - reg_w(gspca_dev, 0x06, 0x09); - reg_w(gspca_dev, 0x07, 0x0f); - reg_w(gspca_dev, 0x08, 0x09); - reg_w(gspca_dev, 0x09, 0x00); - reg_w(gspca_dev, 0x0c, 0x07); - reg_w(gspca_dev, 0x0d, 0x00); - reg_w(gspca_dev, 0x0e, 0x00); - reg_w(gspca_dev, 0x0f, 0x62); - reg_w(gspca_dev, 0x10, 0x08); - reg_w(gspca_dev, 0x12, 0x07); - reg_w(gspca_dev, 0x13, 0x00); - reg_w(gspca_dev, 0x14, 0x00); - reg_w(gspca_dev, 0x15, 0x00); - reg_w(gspca_dev, 0x16, 0x00); - reg_w(gspca_dev, 0x17, 0x00); - reg_w(gspca_dev, 0x18, 0x00); - reg_w(gspca_dev, 0x19, 0x00); - reg_w(gspca_dev, 0x1a, 0x00); - reg_w(gspca_dev, 0x1b, 0x03); - reg_w(gspca_dev, 0x1c, 0xa0); - reg_w(gspca_dev, 0x1d, 0x01); - reg_w(gspca_dev, 0x1e, 0xf4); - reg_w(gspca_dev, 0x21, 0x00); - reg_w(gspca_dev, 0x22, 0x08); - reg_w(gspca_dev, 0x24, 0x03); - reg_w(gspca_dev, 0x26, 0x00); - reg_w(gspca_dev, 0x27, 0x01); - reg_w(gspca_dev, 0x28, 0xca); - reg_w(gspca_dev, 0x29, 0x10); - reg_w(gspca_dev, 0x2a, 0x06); - reg_w(gspca_dev, 0x2b, 0x78); - reg_w(gspca_dev, 0x2c, 0x00); - reg_w(gspca_dev, 0x2d, 0x00); - reg_w(gspca_dev, 0x2e, 0x00); - reg_w(gspca_dev, 0x2f, 0x00); - reg_w(gspca_dev, 0x30, 0x23); - reg_w(gspca_dev, 0x31, 0x28); - reg_w(gspca_dev, 0x32, 0x04); - reg_w(gspca_dev, 0x33, 0x11); - reg_w(gspca_dev, 0x34, 0x00); - reg_w(gspca_dev, 0x35, 0x00); - reg_w(gspca_dev, 0x11, 0x01); + if (sd->sensor == SENSOR_PAC7302) + reg_w_var(gspca_dev, start_7302); + else + reg_w_var(gspca_dev, start_7311); + setcontrast(gspca_dev); setbrightness(gspca_dev); setcolors(gspca_dev); @@ -416,7 +580,7 @@ static void sd_start(struct gspca_dev *gspca_dev) /* set correct resolution */ switch (gspca_dev->cam.cam_mode[(int) gspca_dev->curr_mode].priv) { - case 2: /* 160x120 */ + case 2: /* 160x120 pac7311 */ reg_w(gspca_dev, 0xff, 0x04); reg_w(gspca_dev, 0x02, 0x03); reg_w(gspca_dev, 0xff, 0x01); @@ -426,7 +590,7 @@ static void sd_start(struct gspca_dev *gspca_dev) /* reg_w(gspca_dev, 0x80, 0x69); */ reg_w(gspca_dev, 0x87, 0x10); break; - case 1: /* 320x240 */ + case 1: /* 320x240 pac7311 */ reg_w(gspca_dev, 0xff, 0x04); reg_w(gspca_dev, 0x02, 0x03); reg_w(gspca_dev, 0xff, 0x01); @@ -436,6 +600,8 @@ static void sd_start(struct gspca_dev *gspca_dev) reg_w(gspca_dev, 0x87, 0x11); break; case 0: /* 640x480 */ + if (sd->sensor == SENSOR_PAC7302) + break; reg_w(gspca_dev, 0xff, 0x04); reg_w(gspca_dev, 0x02, 0x03); reg_w(gspca_dev, 0xff, 0x01); @@ -448,12 +614,25 @@ static void sd_start(struct gspca_dev *gspca_dev) /* start stream */ reg_w(gspca_dev, 0xff, 0x01); - reg_w(gspca_dev, 0x78, 0x04); - reg_w(gspca_dev, 0x78, 0x05); + if (sd->sensor == SENSOR_PAC7302) { + reg_w(gspca_dev, 0x78, 0x01); + reg_w(gspca_dev, 0xff, 0x01); + reg_w(gspca_dev, 0x78, 0x01); + } else { + reg_w(gspca_dev, 0x78, 0x04); + reg_w(gspca_dev, 0x78, 0x05); + } } static void sd_stopN(struct gspca_dev *gspca_dev) { + struct sd *sd = (struct sd *) gspca_dev; + + if (sd->sensor == SENSOR_PAC7302) { + reg_w(gspca_dev, 0x78, 0x00); + reg_w(gspca_dev, 0x78, 0x00); + return; + } reg_w(gspca_dev, 0xff, 0x04); reg_w(gspca_dev, 0x27, 0x80); reg_w(gspca_dev, 0x28, 0xca); @@ -468,21 +647,17 @@ static void sd_stopN(struct gspca_dev *gspca_dev) static void sd_stop0(struct gspca_dev *gspca_dev) { + struct sd *sd = (struct sd *) gspca_dev; + + if (sd->sensor == SENSOR_PAC7302) { + reg_w(gspca_dev, 0xff, 0x01); + reg_w(gspca_dev, 0x78, 0x40); + } } /* this function is called at close time */ static void sd_close(struct gspca_dev *gspca_dev) { - reg_w(gspca_dev, 0xff, 0x04); - reg_w(gspca_dev, 0x27, 0x80); - reg_w(gspca_dev, 0x28, 0xca); - reg_w(gspca_dev, 0x29, 0x53); - reg_w(gspca_dev, 0x2a, 0x0e); - reg_w(gspca_dev, 0xff, 0x01); - reg_w(gspca_dev, 0x3e, 0x20); - reg_w(gspca_dev, 0x78, 0x04); /* Bit_0=start stream, Bit_7=LED */ - reg_w(gspca_dev, 0x78, 0x44); /* Bit_0=start stream, Bit_7=LED */ - reg_w(gspca_dev, 0x78, 0x44); /* Bit_0=start stream, Bit_7=LED */ } static void do_autogain(struct gspca_dev *gspca_dev) @@ -509,10 +684,17 @@ static void do_autogain(struct gspca_dev *gspca_dev) else if (Gbright < 4) Gbright = 4; PDEBUG(D_FRAM, "gbright %d", Gbright); - reg_w(gspca_dev, 0xff, 0x04); - reg_w(gspca_dev, 0x0f, Gbright); - /* load registers to sensor (Bit 0, auto clear) */ - reg_w(gspca_dev, 0x11, 0x01); + if (sd->sensor == SENSOR_PAC7302) { + reg_w(gspca_dev, 0xff, 0x03); + reg_w(gspca_dev, 0x10, Gbright); + /* load registers to sensor (Bit 0, auto clear) */ + reg_w(gspca_dev, 0x11, 0x01); + } else { + reg_w(gspca_dev, 0xff, 0x04); + reg_w(gspca_dev, 0x0f, Gbright); + /* load registers to sensor (Bit 0, auto clear) */ + reg_w(gspca_dev, 0x11, 0x01); + } } } @@ -636,15 +818,6 @@ static void sd_pkt_scan(struct gspca_dev *gspca_dev, } } -static void getbrightness(struct gspca_dev *gspca_dev) -{ -/* sd->brightness = reg_r(gspca_dev, 0x08); - return sd->brightness; */ -/* PDEBUG(D_CONF, "Called pac7311_getbrightness: Not implemented yet"); */ -} - - - static int sd_setbrightness(struct gspca_dev *gspca_dev, __s32 val) { struct sd *sd = (struct sd *) gspca_dev; @@ -659,7 +832,6 @@ static int sd_getbrightness(struct gspca_dev *gspca_dev, __s32 *val) { struct sd *sd = (struct sd *) gspca_dev; - getbrightness(gspca_dev); *val = sd->brightness; return 0; } @@ -678,7 +850,6 @@ static int sd_getcontrast(struct gspca_dev *gspca_dev, __s32 *val) { struct sd *sd = (struct sd *) gspca_dev; -/* getcontrast(gspca_dev); */ *val = sd->contrast; return 0; } @@ -697,7 +868,6 @@ static int sd_getcolors(struct gspca_dev *gspca_dev, __s32 *val) { struct sd *sd = (struct sd *) gspca_dev; -/* getcolors(gspca_dev); */ *val = sd->colors; return 0; } @@ -737,13 +907,13 @@ static struct sd_desc sd_desc = { /* -- module initialisation -- */ static __devinitdata struct usb_device_id device_table[] = { - {USB_DEVICE(0x093a, 0x2600)}, - {USB_DEVICE(0x093a, 0x2601)}, - {USB_DEVICE(0x093a, 0x2603)}, - {USB_DEVICE(0x093a, 0x2608)}, - {USB_DEVICE(0x093a, 0x260e)}, - {USB_DEVICE(0x093a, 0x260f)}, - {USB_DEVICE(0x093a, 0x2621)}, + {USB_DEVICE(0x093a, 0x2600), .driver_info = SENSOR_PAC7311}, + {USB_DEVICE(0x093a, 0x2601), .driver_info = SENSOR_PAC7311}, + {USB_DEVICE(0x093a, 0x2603), .driver_info = SENSOR_PAC7311}, + {USB_DEVICE(0x093a, 0x2608), .driver_info = SENSOR_PAC7311}, + {USB_DEVICE(0x093a, 0x260e), .driver_info = SENSOR_PAC7311}, + {USB_DEVICE(0x093a, 0x260f), .driver_info = SENSOR_PAC7311}, + {USB_DEVICE(0x093a, 0x2621), .driver_info = SENSOR_PAC7302}, {} }; MODULE_DEVICE_TABLE(usb, device_table); -- cgit v0.10.2 From 9d5c1251bfc10a0e864352f45e272331f65b3420 Mon Sep 17 00:00:00 2001 From: Jean-Francois Moine Date: Wed, 3 Sep 2008 16:47:26 -0300 Subject: V4L/DVB (8665): gspca: Fix the 640x480 resolution of the webcam 093a:2621. Signed-off-by: Jean-Francois Moine Signed-off-by: Mauro Carvalho Chehab diff --git a/drivers/media/video/gspca/sonixj.c b/drivers/media/video/gspca/sonixj.c index 151e1b6..0a20db8 100644 --- a/drivers/media/video/gspca/sonixj.c +++ b/drivers/media/video/gspca/sonixj.c @@ -1136,7 +1136,6 @@ static void sd_start(struct gspca_dev *gspca_dev) break; case SENSOR_OM6802: om6802_InitSensor(gspca_dev); - reg1 = 0x46; /* 640 clk 24Mz */ reg17 = 0x64; /* 640 MCKSIZE */ break; case SENSOR_OV7648: -- cgit v0.10.2 From 8559e8da31f37e2916195f44bbe79a61008782df Mon Sep 17 00:00:00 2001 From: Jean-Francois Moine Date: Wed, 3 Sep 2008 16:47:27 -0300 Subject: V4L/DVB (8666): gspca: Bad scanning of frames in pac7311. The previous change in packet scanning did not work, Also, autogain was no more treated at interrupt level. Signed-off-by: Jean-Francois Moine Signed-off-by: Mauro Carvalho Chehab diff --git a/drivers/media/video/gspca/pac7311.c b/drivers/media/video/gspca/pac7311.c index 034c00d..730b4a1 100644 --- a/drivers/media/video/gspca/pac7311.c +++ b/drivers/media/video/gspca/pac7311.c @@ -702,8 +702,16 @@ static void do_autogain(struct gspca_dev *gspca_dev) static void put_jpeg_head(struct gspca_dev *gspca_dev, struct gspca_frame *frame) { + struct sd *sd = (struct sd *) gspca_dev; unsigned char tmpbuf[4]; + if (sd->ag_cnt >= 0) { + if (--sd->ag_cnt < 0) { + sd->ag_cnt = AG_CNT_START; + atomic_set(&sd->avg_lum, sd->lum_sum / AG_CNT_START); + atomic_set(&sd->do_gain, 1); + } + } gspca_frame_add(gspca_dev, FIRST_PACKET, frame, (__u8 *) pac7311_jpeg_header, 12); @@ -727,7 +735,7 @@ static void sd_pkt_scan(struct gspca_dev *gspca_dev, struct sd *sd = (struct sd *) gspca_dev; int i; -#define INTER_FRAME 0x53 +#define INTER_FRAME 0x53 /* eof + inter frame + sof */ #define LUM_OFFSET 0x1e /* reverse offset / start of frame */ /* @@ -746,11 +754,18 @@ static void sd_pkt_scan(struct gspca_dev *gspca_dev, if (sd->tosof == 0) { /* if inside a frame */ /* check for 'ff ff ff xx' at start and at end of packet */ - /* (len is always >= 3) */ + /* (len is always >= 3 and xx never ff) */ switch (sd->ffnb) { case 1: - if (data[0] != 0xff) + if (data[0] != 0xff) { /* can be '00' only */ + __u8 ff; + + sd->ffnb = 0; + ff = 0xff; + gspca_frame_add(gspca_dev, INTER_PACKET, + frame, &ff, 1); break; /* keep 'ff 00' */ + } /* fall thru */ case 2: case 3: @@ -775,16 +790,13 @@ static void sd_pkt_scan(struct gspca_dev *gspca_dev, } } else { /* outside a frame */ - /* - * get the luminosity - * and go to the start of frame - */ + /* get the luminosity and go to the start of frame */ data += sd->tosof; len -= sd->tosof; if (sd->tosof > LUM_OFFSET) sd->lum_sum += data[-LUM_OFFSET]; - put_jpeg_head(gspca_dev, frame); sd->tosof = 0; + put_jpeg_head(gspca_dev, frame); } for (i = 0; i < len; i++) { @@ -792,10 +804,9 @@ static void sd_pkt_scan(struct gspca_dev *gspca_dev, continue; switch (data[i + 1]) { case 0xd9: /* end of frame */ - i += 2; frame = gspca_frame_add(gspca_dev, LAST_PACKET, - frame, data, i); + frame, data, i + 2); data += i + INTER_FRAME; len -= i + INTER_FRAME; i = 0; @@ -816,6 +827,8 @@ static void sd_pkt_scan(struct gspca_dev *gspca_dev, break; } } + gspca_frame_add(gspca_dev, INTER_PACKET, + frame, data, i); } static int sd_setbrightness(struct gspca_dev *gspca_dev, __s32 val) -- cgit v0.10.2 From 3466234229e6535a061f5f63a87bfb12c833d96a Mon Sep 17 00:00:00 2001 From: Hans de Goede Date: Wed, 3 Sep 2008 16:47:28 -0300 Subject: V4L/DVB (8667): gspca: Bad probe of Z-Star/Vimicro webcams with pas106 sensor. This patch moves the detection of the 2wr SIF pas106b sensor to before detecting other sensors. Patch change by jfm: Check SIF for identified webcams only. Signed-off-by: Hans de Goede Signed-off-by: Jean-Francois Moine Signed-off-by: Mauro Carvalho Chehab diff --git a/drivers/media/video/gspca/zc3xx.c b/drivers/media/video/gspca/zc3xx.c index bc7d0ee..d36f4d7 100644 --- a/drivers/media/video/gspca/zc3xx.c +++ b/drivers/media/video/gspca/zc3xx.c @@ -6964,8 +6964,13 @@ static int zcxx_probeSensor(struct gspca_dev *gspca_dev) case SENSOR_MC501CB: return -1; /* don't probe */ case SENSOR_TAS5130C_VF0250: - /* may probe but with write in reg 0x0010 */ + /* may probe but with no write in reg 0x0010 */ return -1; /* don't probe */ + case SENSOR_PAS106: + sensor = sif_probe(gspca_dev); + if (sensor >= 0) + return sensor; + break; } sensor = vga_2wr_probe(gspca_dev); if (sensor >= 0) { @@ -6974,12 +6979,10 @@ static int zcxx_probeSensor(struct gspca_dev *gspca_dev) /* next probe is needed for OmniVision ? */ } sensor2 = vga_3wr_probe(gspca_dev); - if (sensor2 >= 0) { - if (sensor >= 0) - return sensor; - return sensor2; - } - return sif_probe(gspca_dev); + if (sensor2 >= 0 + && sensor >= 0) + return sensor; + return sensor2; } /* this function is called at probe time */ @@ -7502,14 +7505,14 @@ static const __devinitdata struct usb_device_id device_table[] = { {USB_DEVICE(0x041e, 0x041e)}, #ifndef CONFIG_USB_ZC0301 {USB_DEVICE(0x041e, 0x4017)}, - {USB_DEVICE(0x041e, 0x401c)}, + {USB_DEVICE(0x041e, 0x401c), .driver_info = SENSOR_PAS106}, {USB_DEVICE(0x041e, 0x401e)}, {USB_DEVICE(0x041e, 0x401f)}, #endif {USB_DEVICE(0x041e, 0x4029)}, #ifndef CONFIG_USB_ZC0301 - {USB_DEVICE(0x041e, 0x4034)}, - {USB_DEVICE(0x041e, 0x4035)}, + {USB_DEVICE(0x041e, 0x4034), .driver_info = SENSOR_PAS106}, + {USB_DEVICE(0x041e, 0x4035), .driver_info = SENSOR_PAS106}, {USB_DEVICE(0x041e, 0x4036)}, {USB_DEVICE(0x041e, 0x403a)}, #endif @@ -7541,10 +7544,10 @@ static const __devinitdata struct usb_device_id device_table[] = { {USB_DEVICE(0x046d, 0x08d8)}, {USB_DEVICE(0x046d, 0x08da)}, {USB_DEVICE(0x046d, 0x08dd), .driver_info = SENSOR_MC501CB}, - {USB_DEVICE(0x0471, 0x0325)}, - {USB_DEVICE(0x0471, 0x0326)}, - {USB_DEVICE(0x0471, 0x032d)}, - {USB_DEVICE(0x0471, 0x032e)}, + {USB_DEVICE(0x0471, 0x0325), .driver_info = SENSOR_PAS106}, + {USB_DEVICE(0x0471, 0x0326), .driver_info = SENSOR_PAS106}, + {USB_DEVICE(0x0471, 0x032d), .driver_info = SENSOR_PAS106}, + {USB_DEVICE(0x0471, 0x032e), .driver_info = SENSOR_PAS106}, {USB_DEVICE(0x055f, 0xc005)}, #ifndef CONFIG_USB_ZC0301 {USB_DEVICE(0x055f, 0xd003)}, -- cgit v0.10.2 From 5bb0f21a46281b021897d2c56d50685c1939b5ee Mon Sep 17 00:00:00 2001 From: Jean-Francois Moine Date: Wed, 3 Sep 2008 16:47:29 -0300 Subject: V4L/DVB (8668): gspca: Conflict GSPCA / ET61X251 for the webcam 102c:6251. Fix a double handling of 102c:6251 and no handling of 102c:6151 when both drivers GSPCA and ET61X251. Signed-off-by: Jean-Francois Moine Signed-off-by: Mauro Carvalho Chehab diff --git a/drivers/media/video/gspca/etoms.c b/drivers/media/video/gspca/etoms.c index 1dbe92d..ca23c3f 100644 --- a/drivers/media/video/gspca/etoms.c +++ b/drivers/media/video/gspca/etoms.c @@ -904,10 +904,10 @@ static struct sd_desc sd_desc = { /* -- module initialisation -- */ static __devinitdata struct usb_device_id device_table[] = { -#ifndef CONFIG_USB_ET61X251 {USB_DEVICE(0x102c, 0x6151), .driver_info = SENSOR_PAS106}, -#endif +#ifndef CONFIG_USB_ET61X251 {USB_DEVICE(0x102c, 0x6251), .driver_info = SENSOR_TAS5130CXX}, +#endif {} }; -- cgit v0.10.2 From 6c9d3c59e6fdb8dfadaf7ba38f1d0b64ff066b36 Mon Sep 17 00:00:00 2001 From: Jean-Francois Moine Date: Wed, 3 Sep 2008 16:47:30 -0300 Subject: V4L/DVB (8669): gspca: Add white balance control for spca561 rev 012A. Signed-off-by: Jean-Francois Moine Signed-off-by: Mauro Carvalho Chehab diff --git a/drivers/media/video/gspca/spca561.c b/drivers/media/video/gspca/spca561.c index 1073ac3..02e2744 100644 --- a/drivers/media/video/gspca/spca561.c +++ b/drivers/media/video/gspca/spca561.c @@ -34,6 +34,7 @@ struct sd { unsigned short contrast; __u8 brightness; + __u8 white; __u8 autogain; __u8 chip_revision; @@ -46,11 +47,12 @@ static int sd_setbrightness(struct gspca_dev *gspca_dev, __s32 val); static int sd_getbrightness(struct gspca_dev *gspca_dev, __s32 *val); static int sd_setcontrast(struct gspca_dev *gspca_dev, __s32 val); static int sd_getcontrast(struct gspca_dev *gspca_dev, __s32 *val); +static int sd_setwhite(struct gspca_dev *gspca_dev, __s32 val); +static int sd_getwhite(struct gspca_dev *gspca_dev, __s32 *val); static int sd_setautogain(struct gspca_dev *gspca_dev, __s32 val); static int sd_getautogain(struct gspca_dev *gspca_dev, __s32 *val); static struct ctrl sd_ctrls[] = { -#define SD_BRIGHTNESS 0 { { .id = V4L2_CID_BRIGHTNESS, @@ -59,12 +61,12 @@ static struct ctrl sd_ctrls[] = { .minimum = 0, .maximum = 63, .step = 1, - .default_value = 32, +#define BRIGHTNESS_DEF 32 + .default_value = BRIGHTNESS_DEF, }, .set = sd_setbrightness, .get = sd_getbrightness, }, -#define SD_CONTRAST 1 { { .id = V4L2_CID_CONTRAST, @@ -73,12 +75,26 @@ static struct ctrl sd_ctrls[] = { .minimum = 0, .maximum = 0x3fff, .step = 1, - .default_value = 0x2000, +#define CONTRAST_DEF 0x2000 + .default_value = CONTRAST_DEF, }, .set = sd_setcontrast, .get = sd_getcontrast, }, -#define SD_AUTOGAIN 2 + { + { + .id = V4L2_CID_DO_WHITE_BALANCE, + .type = V4L2_CTRL_TYPE_INTEGER, + .name = "While Balance", + .minimum = 0, + .maximum = 0x7f, + .step = 1, +#define WHITE_DEF 40 + .default_value = WHITE_DEF, + }, + .set = sd_setwhite, + .get = sd_getwhite, + }, { { .id = V4L2_CID_AUTOGAIN, @@ -87,7 +103,8 @@ static struct ctrl sd_ctrls[] = { .minimum = 0, .maximum = 1, .step = 1, - .default_value = 1, +#define AUTOGAIN_DEF 1 + .default_value = AUTOGAIN_DEF, }, .set = sd_setautogain, .get = sd_getautogain, @@ -438,7 +455,7 @@ static const __u16 spca561_init_data[][2] = { {0x0035, 0x8801}, /* 0x14 - set gain general */ {0x001f, 0x8805}, /* 0x14 */ {0x0000, 0x8800}, - {0x0030, 0x8112}, + {0x000e, 0x8112}, /* white balance - was 30 */ {} }; @@ -478,9 +495,10 @@ static const __u16 Pb100_2map8300[][2] = { }; static const __u16 spca561_161rev12A_data1[][2] = { - {0x21, 0x8118}, - {0x01, 0x8114}, - {0x00, 0x8112}, + {0x29, 0x8118}, /* white balance - was 21 */ + {0x08, 0x8114}, /* white balance - was 01 */ + {0x0e, 0x8112}, /* white balance - was 00 */ + {0x00, 0x8102}, /* white balance - new */ {0x92, 0x8804}, {0x04, 0x8802}, /* windows uses 08 */ {} @@ -505,14 +523,16 @@ static const __u16 spca561_161rev12A_data2[][2] = { {0xb0, 0x8603}, /* sensor gains */ + {0x07, 0x8601}, /* white balance - new */ + {0x07, 0x8602}, /* white balance - new */ {0x00, 0x8610}, /* *red */ {0x00, 0x8611}, /* 3f *green */ {0x00, 0x8612}, /* green *blue */ {0x00, 0x8613}, /* blue *green */ - {0x35, 0x8614}, /* green *red */ - {0x35, 0x8615}, /* 40 *green */ - {0x35, 0x8616}, /* 7a *blue */ - {0x35, 0x8617}, /* 40 *green */ + {0x43, 0x8614}, /* green *red - white balance - was 0x35 */ + {0x40, 0x8615}, /* 40 *green - white balance - was 0x35 */ + {0x71, 0x8616}, /* 7a *blue - white balance - was 0x35 */ + {0x40, 0x8617}, /* 40 *green - white balance - was 0x35 */ {0x0c, 0x8620}, /* 0c */ {0xc8, 0x8631}, /* c8 */ @@ -527,6 +547,7 @@ static const __u16 spca561_161rev12A_data2[][2] = { {0xdf, 0x863c}, /* df */ {0xf0, 0x8505}, {0x32, 0x850a}, + {0x99, 0x8700}, /* - white balance - new */ {} }; @@ -588,9 +609,10 @@ static int sd_config(struct gspca_dev *gspca_dev, cam->nmodes = sizeof sif_mode / sizeof sif_mode[0]; sd->chip_revision = id->driver_info; - sd->brightness = sd_ctrls[SD_BRIGHTNESS].qctrl.default_value; - sd->contrast = sd_ctrls[SD_CONTRAST].qctrl.default_value; - sd->autogain = sd_ctrls[SD_AUTOGAIN].qctrl.default_value; + sd->brightness = BRIGHTNESS_DEF; + sd->contrast = CONTRAST_DEF; + sd->autogain = AUTOGAIN_DEF; + sd->white = WHITE_DEF; return 0; } @@ -628,15 +650,18 @@ static void setcontrast(struct gspca_dev *gspca_dev) reg_w_val(dev, lowb, 0x8653); reg_w_val(dev, lowb, 0x8654); break; - case Rev012A: { + default: { +/* case Rev012A: { */ __u8 Reg8391[] = { 0x00, 0x00, 0x00, 0x00, 0x0c, 0x00, 0x00, 0x00 }; /* Write camera sensor settings */ expotimes = (sd->contrast >> 5) & 0x07ff; + /* exposure is in 8309 2b, range 0120 - 5720 */ Reg8391[0] = expotimes & 0xff; /* exposure */ Reg8391[1] = 0x18 | (expotimes >> 8); Reg8391[2] = sd->brightness; /* gain */ + /* gain in 8335, 2b range 0000 - 2400 */ reg_w_buf(gspca_dev, 0x8391, Reg8391, 8); reg_w_buf(gspca_dev, 0x8390, Reg8391, 8); break; @@ -644,6 +669,34 @@ static void setcontrast(struct gspca_dev *gspca_dev) } } +static void setwhite(struct gspca_dev *gspca_dev) +{ + struct sd *sd = (struct sd *) gspca_dev; + __u16 white; + __u8 reg8614, reg8616; + + switch (sd->chip_revision) { + case Rev072A: + /* no such hardware */ + break; + default: +/* case Rev012A: */ + white = sd->white; + if (sd->white == 0) { + PDEBUG(D_CONF, "Discarding null whiteness"); + break; + } + /* try to emulate MS-win as possible */ + if (white < 0x45) + reg8616 = white; + else + reg8616 = 0x93 + (white >> 2); + reg8614 = 0x28 + (white >> 4); + reg_w_val(gspca_dev->dev, reg8616, 0x8616); + reg_w_val(gspca_dev->dev, reg8614, 0x8614); + } +} + static void setautogain(struct gspca_dev *gspca_dev) { struct sd *sd = (struct sd *) gspca_dev; @@ -714,6 +767,7 @@ static void sd_start(struct gspca_dev *gspca_dev) reg_w_val(gspca_dev->dev, 0x8112, 0x1e | 0x20); reg_w_val(gspca_dev->dev, 0x850b, 0x03); setcontrast(gspca_dev); + setwhite(gspca_dev); break; } } @@ -721,6 +775,7 @@ static void sd_start(struct gspca_dev *gspca_dev) static void sd_stopN(struct gspca_dev *gspca_dev) { reg_w_val(gspca_dev->dev, 0x8112, 0x20); + reg_w_val(gspca_dev->dev, 0x8102, 0x00); /* white balance - new */ } static void sd_stop0(struct gspca_dev *gspca_dev) @@ -968,6 +1023,25 @@ static int sd_getautogain(struct gspca_dev *gspca_dev, __s32 *val) return 0; } +/* white balance - new */ +static int sd_setwhite(struct gspca_dev *gspca_dev, __s32 val) +{ + struct sd *sd = (struct sd *) gspca_dev; + + sd->white = val; + if (gspca_dev->streaming) + setwhite(gspca_dev); + return 0; +} + +static int sd_getwhite(struct gspca_dev *gspca_dev, __s32 *val) +{ + struct sd *sd = (struct sd *) gspca_dev; + + *val = sd->white; + return 0; +} + /* sub-driver description */ static const struct sd_desc sd_desc = { .name = MODULE_NAME, -- cgit v0.10.2 From a0b508c2d7d0de0e46555793e334e35381716825 Mon Sep 17 00:00:00 2001 From: Jean-Francois Moine Date: Wed, 3 Sep 2008 16:47:31 -0300 Subject: V4L/DVB (8671): gspca: Remove the unused field 'dev_name' of the device structure. Signed-off-by: Jean-Francois Moine Signed-off-by: Mauro Carvalho Chehab diff --git a/drivers/media/video/gspca/gspca.h b/drivers/media/video/gspca/gspca.h index 67e4489..5cb5845 100644 --- a/drivers/media/video/gspca/gspca.h +++ b/drivers/media/video/gspca/gspca.h @@ -56,7 +56,6 @@ extern int gspca_debug; /* device information - set at probe time */ struct cam { - char *dev_name; struct v4l2_pix_format *cam_mode; /* size nmodes */ char nmodes; __u8 epaddr; diff --git a/drivers/media/video/gspca/pac207.c b/drivers/media/video/gspca/pac207.c index 7ef18d5..cee45b0 100644 --- a/drivers/media/video/gspca/pac207.c +++ b/drivers/media/video/gspca/pac207.c @@ -271,7 +271,6 @@ static int sd_config(struct gspca_dev *gspca_dev, " (vid/pid 0x%04X:0x%04X)", id->idVendor, id->idProduct); cam = &gspca_dev->cam; - cam->dev_name = (char *) id->driver_info; cam->epaddr = 0x05; cam->cam_mode = sif_mode; cam->nmodes = ARRAY_SIZE(sif_mode); diff --git a/drivers/media/video/gspca/spca561.c b/drivers/media/video/gspca/spca561.c index 02e2744..a9f7c99 100644 --- a/drivers/media/video/gspca/spca561.c +++ b/drivers/media/video/gspca/spca561.c @@ -602,7 +602,6 @@ static int sd_config(struct gspca_dev *gspca_dev, } cam = &gspca_dev->cam; - cam->dev_name = (char *) id->driver_info; cam->epaddr = 0x01; gspca_dev->nbalt = 7 + 1; /* choose alternate 7 first */ cam->cam_mode = sif_mode; -- cgit v0.10.2 From 7879d459f1601be742d0d63930d17cd4aac956fd Mon Sep 17 00:00:00 2001 From: Jean-Francois Moine Date: Wed, 3 Sep 2008 16:47:32 -0300 Subject: V4L/DVB (8672): gspca: Big rewrite of spca561. Bug register/value inversions in USB exchanges. Exposure and gain controls added for rev 12a. Separate the functions and controls of the revisions 12a and 72a. Signed-off-by: Jean-Francois Moine Signed-off-by: Mauro Carvalho Chehab diff --git a/drivers/media/video/gspca/spca561.c b/drivers/media/video/gspca/spca561.c index a9f7c99..0a2b8bc 100644 --- a/drivers/media/video/gspca/spca561.c +++ b/drivers/media/video/gspca/spca561.c @@ -32,85 +32,44 @@ MODULE_LICENSE("GPL"); struct sd { struct gspca_dev gspca_dev; /* !! must be the first item */ - unsigned short contrast; - __u8 brightness; - __u8 white; + __u16 contrast; /* rev72a only */ +#define CONTRAST_MIN 0x0000 +#define CONTRAST_DEF 0x2000 +#define CONTRAST_MAX 0x3fff + + __u16 exposure; /* rev12a only */ +#define EXPOSURE_MIN 0x0120 +#define EXPOSURE_DEF 0x20ae +#define EXPOSURE_MAX 0x5720 + + __u8 brightness; /* rev72a only */ +#define BRIGHTNESS_MIN 0 +#define BRIGHTNESS_DEF 32 +#define BRIGHTNESS_MAX 63 + + __u8 white; /* rev12a only */ +#define WHITE_MIN 0 +#define WHITE_DEF 0x40 +#define WHITE_MAX 0x7f + __u8 autogain; +#define AUTOGAIN_MIN 0 +#define AUTOGAIN_DEF 1 +#define AUTOGAIN_MAX 1 + + __u8 gain; /* rev12a only */ +#define GAIN_MIN 0x0 +#define GAIN_DEF 0x24 +#define GAIN_MAX 0x24 __u8 chip_revision; +#define Rev012A 0 +#define Rev072A 1 + signed char ag_cnt; #define AG_CNT_START 13 }; -/* V4L2 controls supported by the driver */ -static int sd_setbrightness(struct gspca_dev *gspca_dev, __s32 val); -static int sd_getbrightness(struct gspca_dev *gspca_dev, __s32 *val); -static int sd_setcontrast(struct gspca_dev *gspca_dev, __s32 val); -static int sd_getcontrast(struct gspca_dev *gspca_dev, __s32 *val); -static int sd_setwhite(struct gspca_dev *gspca_dev, __s32 val); -static int sd_getwhite(struct gspca_dev *gspca_dev, __s32 *val); -static int sd_setautogain(struct gspca_dev *gspca_dev, __s32 val); -static int sd_getautogain(struct gspca_dev *gspca_dev, __s32 *val); - -static struct ctrl sd_ctrls[] = { - { - { - .id = V4L2_CID_BRIGHTNESS, - .type = V4L2_CTRL_TYPE_INTEGER, - .name = "Brightness", - .minimum = 0, - .maximum = 63, - .step = 1, -#define BRIGHTNESS_DEF 32 - .default_value = BRIGHTNESS_DEF, - }, - .set = sd_setbrightness, - .get = sd_getbrightness, - }, - { - { - .id = V4L2_CID_CONTRAST, - .type = V4L2_CTRL_TYPE_INTEGER, - .name = "Contrast", - .minimum = 0, - .maximum = 0x3fff, - .step = 1, -#define CONTRAST_DEF 0x2000 - .default_value = CONTRAST_DEF, - }, - .set = sd_setcontrast, - .get = sd_getcontrast, - }, - { - { - .id = V4L2_CID_DO_WHITE_BALANCE, - .type = V4L2_CTRL_TYPE_INTEGER, - .name = "While Balance", - .minimum = 0, - .maximum = 0x7f, - .step = 1, -#define WHITE_DEF 40 - .default_value = WHITE_DEF, - }, - .set = sd_setwhite, - .get = sd_getwhite, - }, - { - { - .id = V4L2_CID_AUTOGAIN, - .type = V4L2_CTRL_TYPE_BOOLEAN, - .name = "Auto Gain", - .minimum = 0, - .maximum = 1, - .step = 1, -#define AUTOGAIN_DEF 1 - .default_value = AUTOGAIN_DEF, - }, - .set = sd_setautogain, - .get = sd_getautogain, - }, -}; - static struct v4l2_pix_format sif_mode[] = { {160, 120, V4L2_PIX_FMT_SGBRG8, V4L2_FIELD_NONE, .bytesperline = 160, @@ -160,12 +119,8 @@ static struct v4l2_pix_format sif_mode[] = { #define SPCA561_INDEX_I2C_BASE 0x8800 #define SPCA561_SNAPBIT 0x20 #define SPCA561_SNAPCTRL 0x40 -enum { - Rev072A = 0, - Rev012A, -}; -static void reg_w_val(struct usb_device *dev, __u16 index, __u16 value) +static void reg_w_val(struct usb_device *dev, __u16 index, __u8 value) { int ret; @@ -215,12 +170,6 @@ static void reg_w_buf(struct gspca_dev *gspca_dev, index, gspca_dev->usb_buf, len, 500); } -static void i2c_init(struct gspca_dev *gspca_dev, __u8 mode) -{ - reg_w_val(gspca_dev->dev, 0x92, 0x8804); - reg_w_val(gspca_dev->dev, mode, 0x8802); -} - static void i2c_write(struct gspca_dev *gspca_dev, __u16 valeur, __u16 reg) { int retry = 60; @@ -229,9 +178,9 @@ static void i2c_write(struct gspca_dev *gspca_dev, __u16 valeur, __u16 reg) DataLow = valeur; DataHight = valeur >> 8; - reg_w_val(gspca_dev->dev, reg, 0x8801); - reg_w_val(gspca_dev->dev, DataLow, 0x8805); - reg_w_val(gspca_dev->dev, DataHight, 0x8800); + reg_w_val(gspca_dev->dev, 0x8801, reg); + reg_w_val(gspca_dev->dev, 0x8805, DataLow); + reg_w_val(gspca_dev->dev, 0x8800, DataHight); while (retry--) { reg_r(gspca_dev, 0x8803, 1); if (!gspca_dev->usb_buf[0]) @@ -245,9 +194,9 @@ static int i2c_read(struct gspca_dev *gspca_dev, __u16 reg, __u8 mode) __u8 value; __u8 vallsb; - reg_w_val(gspca_dev->dev, 0x92, 0x8804); - reg_w_val(gspca_dev->dev, reg, 0x8801); - reg_w_val(gspca_dev->dev, (mode | 0x01), 0x8802); + reg_w_val(gspca_dev->dev, 0x8804, 0x92); + reg_w_val(gspca_dev->dev, 0x8801, reg); + reg_w_val(gspca_dev->dev, 0x8802, (mode | 0x01)); while (retry--) { reg_r(gspca_dev, 0x8803, 1); if (!gspca_dev->usb_buf) @@ -459,17 +408,6 @@ static const __u16 spca561_init_data[][2] = { {} }; -static void sensor_reset(struct gspca_dev *gspca_dev) -{ - reg_w_val(gspca_dev->dev, 0x8631, 0xc8); - reg_w_val(gspca_dev->dev, 0x8634, 0xc8); - reg_w_val(gspca_dev->dev, 0x8112, 0x00); - reg_w_val(gspca_dev->dev, 0x8114, 0x00); - reg_w_val(gspca_dev->dev, 0x8118, 0x21); - i2c_init(gspca_dev, 0x14); - i2c_write(gspca_dev, 1, 0x0d); - i2c_write(gspca_dev, 0, 0x0d); -} /******************** QC Express etch2 stuff ********************/ static const __u16 Pb100_1map8300[][2] = { @@ -479,9 +417,9 @@ static const __u16 Pb100_1map8300[][2] = { {0x8303, 0x0125}, /* image area */ {0x8304, 0x0169}, {0x8328, 0x000b}, - {0x833c, 0x0001}, + {0x833c, 0x0001}, /*fixme: win:07*/ - {0x832f, 0x0419}, + {0x832f, 0x1904}, /*fixme: was 0419*/ {0x8307, 0x00aa}, {0x8301, 0x0003}, {0x8302, 0x000e}, @@ -547,7 +485,7 @@ static const __u16 spca561_161rev12A_data2[][2] = { {0xdf, 0x863c}, /* df */ {0xf0, 0x8505}, {0x32, 0x850a}, - {0x99, 0x8700}, /* - white balance - new */ +/* {0x99, 0x8700}, * - white balance - new (removed) */ {} }; @@ -566,9 +504,10 @@ static void sensor_mapwrite(struct gspca_dev *gspca_dev, } static void init_161rev12A(struct gspca_dev *gspca_dev) { - sensor_reset(gspca_dev); +/* sensor_reset(gspca_dev); (not in win) */ write_vector(gspca_dev, spca561_161rev12A_data1); sensor_mapwrite(gspca_dev, Pb100_1map8300); +/*fixme: should be in sd_start*/ write_vector(gspca_dev, spca561_161rev12A_data2); sensor_mapwrite(gspca_dev, Pb100_2map8300); } @@ -605,32 +544,29 @@ static int sd_config(struct gspca_dev *gspca_dev, cam->epaddr = 0x01; gspca_dev->nbalt = 7 + 1; /* choose alternate 7 first */ cam->cam_mode = sif_mode; - cam->nmodes = sizeof sif_mode / sizeof sif_mode[0]; + cam->nmodes = ARRAY_SIZE(sif_mode); sd->chip_revision = id->driver_info; sd->brightness = BRIGHTNESS_DEF; sd->contrast = CONTRAST_DEF; - sd->autogain = AUTOGAIN_DEF; sd->white = WHITE_DEF; + sd->exposure = EXPOSURE_DEF; + sd->autogain = AUTOGAIN_DEF; + sd->gain = GAIN_DEF; return 0; } /* this function is called at open time */ -static int sd_open(struct gspca_dev *gspca_dev) +static int sd_open_12a(struct gspca_dev *gspca_dev) { - struct sd *sd = (struct sd *) gspca_dev; - - switch (sd->chip_revision) { - case Rev072A: - PDEBUG(D_STREAM, "Chip revision id: 072a"); - write_vector(gspca_dev, spca561_init_data); - break; - default: -/* case Rev012A: */ - PDEBUG(D_STREAM, "Chip revision id: 012a"); - init_161rev12A(gspca_dev); - break; - } + PDEBUG(D_STREAM, "Chip revision: 012a"); + init_161rev12A(gspca_dev); + return 0; +} +static int sd_open_72a(struct gspca_dev *gspca_dev) +{ + PDEBUG(D_STREAM, "Chip revision: 072a"); + write_vector(gspca_dev, spca561_init_data); return 0; } @@ -639,28 +575,20 @@ static void setcontrast(struct gspca_dev *gspca_dev) struct sd *sd = (struct sd *) gspca_dev; struct usb_device *dev = gspca_dev->dev; __u8 lowb; - int expotimes; switch (sd->chip_revision) { case Rev072A: lowb = sd->contrast >> 8; - reg_w_val(dev, lowb, 0x8651); - reg_w_val(dev, lowb, 0x8652); - reg_w_val(dev, lowb, 0x8653); - reg_w_val(dev, lowb, 0x8654); + reg_w_val(dev, 0x8651, lowb); + reg_w_val(dev, 0x8652, lowb); + reg_w_val(dev, 0x8653, lowb); + reg_w_val(dev, 0x8654, lowb); break; default: { /* case Rev012A: { */ - __u8 Reg8391[] = - { 0x00, 0x00, 0x00, 0x00, 0x0c, 0x00, 0x00, 0x00 }; - - /* Write camera sensor settings */ - expotimes = (sd->contrast >> 5) & 0x07ff; - /* exposure is in 8309 2b, range 0120 - 5720 */ - Reg8391[0] = expotimes & 0xff; /* exposure */ - Reg8391[1] = 0x18 | (expotimes >> 8); - Reg8391[2] = sd->brightness; /* gain */ - /* gain in 8335, 2b range 0000 - 2400 */ + static const __u8 Reg8391[] = + { 0x92, 0x30, 0x20, 0x00, 0x0c, 0x00, 0x00, 0x00 }; + reg_w_buf(gspca_dev, 0x8391, Reg8391, 8); reg_w_buf(gspca_dev, 0x8390, Reg8391, 8); break; @@ -668,32 +596,44 @@ static void setcontrast(struct gspca_dev *gspca_dev) } } +/* rev12a only */ static void setwhite(struct gspca_dev *gspca_dev) { struct sd *sd = (struct sd *) gspca_dev; __u16 white; __u8 reg8614, reg8616; - switch (sd->chip_revision) { - case Rev072A: - /* no such hardware */ - break; - default: -/* case Rev012A: */ - white = sd->white; - if (sd->white == 0) { - PDEBUG(D_CONF, "Discarding null whiteness"); - break; - } - /* try to emulate MS-win as possible */ - if (white < 0x45) - reg8616 = white; - else - reg8616 = 0x93 + (white >> 2); - reg8614 = 0x28 + (white >> 4); - reg_w_val(gspca_dev->dev, reg8616, 0x8616); - reg_w_val(gspca_dev->dev, reg8614, 0x8614); + white = sd->white; + if (sd->white == 0) { + PDEBUG(D_CONF, "Discarding null whiteness"); + return; } + /* try to emulate MS-win as possible */ + if (white < 0x45) + reg8616 = white; + else + reg8616 = 0x93 + (white >> 2); + reg8614 = 0x28 + (white >> 4); + reg_w_val(gspca_dev->dev, 0x8616, reg8616); + reg_w_val(gspca_dev->dev, 0x8614, reg8614); +} + +/* rev 12a only */ +static void setexposure(struct gspca_dev *gspca_dev) +{ + struct sd *sd = (struct sd *) gspca_dev; + struct usb_device *dev = gspca_dev->dev; + + reg_w_val(dev, 0x8309, sd->gain); +} + +/* rev 12a only */ +static void setgain(struct gspca_dev *gspca_dev) +{ + struct sd *sd = (struct sd *) gspca_dev; + struct usb_device *dev = gspca_dev->dev; + + reg_w_val(dev, 0x8335, sd->gain); } static void setautogain(struct gspca_dev *gspca_dev) @@ -708,67 +648,67 @@ static void setautogain(struct gspca_dev *gspca_dev) } } -static void sd_start(struct gspca_dev *gspca_dev) +static void sd_start_12a(struct gspca_dev *gspca_dev) { - struct sd *sd = (struct sd *) gspca_dev; struct usb_device *dev = gspca_dev->dev; int Clck; __u8 Reg8307[] = { 0xaa, 0x00 }; int mode; mode = gspca_dev->cam.cam_mode[(int) gspca_dev->curr_mode].priv; - switch (sd->chip_revision) { - case Rev072A: - switch (mode) { - default: -/* case 0: - case 1: */ - Clck = 0x25; - break; - case 2: - Clck = 0x22; - break; - case 3: - Clck = 0x21; - break; - } - reg_w_val(dev, 0x8500, mode); /* mode */ - reg_w_val(dev, 0x8700, Clck); /* 0x27 clock */ - reg_w_val(dev, 0x8112, 0x10 | 0x20); - setautogain(gspca_dev); + switch (mode) { + case 0: + case 1: + Clck = 0x8a; + break; + case 2: + Clck = 0x85; break; default: -/* case Rev012A: */ - switch (mode) { - case 0: - case 1: - Clck = 0x8a; - break; - case 2: - Clck = 0x85; - break; - default: - Clck = 0x83; - break; - } - if (mode <= 1) { - /* Use compression on 320x240 and above */ - reg_w_val(dev, 0x8500, 0x10 | mode); - } else { - /* I couldn't get the compression to work below 320x240 - * Fortunately at these resolutions the bandwidth - * is sufficient to push raw frames at ~20fps */ - reg_w_val(dev, 0x8500, mode); - } /* -- qq@kuku.eu.org */ - reg_w_buf(gspca_dev, 0x8307, Reg8307, 2); - reg_w_val(gspca_dev->dev, 0x8700, Clck); - /* 0x8f 0x85 0x27 clock */ - reg_w_val(gspca_dev->dev, 0x8112, 0x1e | 0x20); - reg_w_val(gspca_dev->dev, 0x850b, 0x03); - setcontrast(gspca_dev); - setwhite(gspca_dev); + Clck = 0x83; + break; + } + if (mode <= 1) { + /* Use compression on 320x240 and above */ + reg_w_val(dev, 0x8500, 0x10 | mode); + } else { + /* I couldn't get the compression to work below 320x240 + * Fortunately at these resolutions the bandwidth + * is sufficient to push raw frames at ~20fps */ + reg_w_val(dev, 0x8500, mode); + } /* -- qq@kuku.eu.org */ + reg_w_buf(gspca_dev, 0x8307, Reg8307, 2); + reg_w_val(gspca_dev->dev, 0x8700, Clck); + /* 0x8f 0x85 0x27 clock */ + reg_w_val(gspca_dev->dev, 0x8112, 0x1e | 0x20); + reg_w_val(gspca_dev->dev, 0x850b, 0x03); + setcontrast(gspca_dev); + setwhite(gspca_dev); +} +static void sd_start_72a(struct gspca_dev *gspca_dev) +{ + struct usb_device *dev = gspca_dev->dev; + int Clck; + int mode; + + mode = gspca_dev->cam.cam_mode[(int) gspca_dev->curr_mode].priv; + switch (mode) { + default: +/* case 0: + case 1: */ + Clck = 0x25; + break; + case 2: + Clck = 0x22; + break; + case 3: + Clck = 0x21; break; } + reg_w_val(dev, 0x8500, mode); /* mode */ + reg_w_val(dev, 0x8700, Clck); /* 0x27 clock */ + reg_w_val(dev, 0x8112, 0x10 | 0x20); + setautogain(gspca_dev); } static void sd_stopN(struct gspca_dev *gspca_dev) @@ -787,6 +727,7 @@ static void sd_close(struct gspca_dev *gspca_dev) reg_w_val(gspca_dev->dev, 0x8114, 0); } +/* rev72a only */ static void do_autogain(struct gspca_dev *gspca_dev) { struct sd *sd = (struct sd *) gspca_dev; @@ -895,24 +836,17 @@ static void sd_pkt_scan(struct gspca_dev *gspca_dev, gspca_frame_add(gspca_dev, INTER_PACKET, frame, data, len); } +/* rev 72a only */ static void setbrightness(struct gspca_dev *gspca_dev) { struct sd *sd = (struct sd *) gspca_dev; __u8 value; - switch (sd->chip_revision) { - case Rev072A: - value = sd->brightness; - reg_w_val(gspca_dev->dev, value, 0x8611); - reg_w_val(gspca_dev->dev, value, 0x8612); - reg_w_val(gspca_dev->dev, value, 0x8613); - reg_w_val(gspca_dev->dev, value, 0x8614); - break; - default: -/* case Rev012A: */ - setcontrast(gspca_dev); - break; - } + value = sd->brightness; + reg_w_val(gspca_dev->dev, 0x8611, value); + reg_w_val(gspca_dev->dev, 0x8612, value); + reg_w_val(gspca_dev->dev, 0x8613, value); + reg_w_val(gspca_dev->dev, 0x8614, value); } static void getbrightness(struct gspca_dev *gspca_dev) @@ -920,52 +854,38 @@ static void getbrightness(struct gspca_dev *gspca_dev) struct sd *sd = (struct sd *) gspca_dev; __u16 tot; - switch (sd->chip_revision) { - case Rev072A: - tot = 0; - reg_r(gspca_dev, 0x8611, 1); - tot += gspca_dev->usb_buf[0]; - reg_r(gspca_dev, 0x8612, 1); - tot += gspca_dev->usb_buf[0]; - reg_r(gspca_dev, 0x8613, 1); - tot += gspca_dev->usb_buf[0]; - reg_r(gspca_dev, 0x8614, 1); - tot += gspca_dev->usb_buf[0]; - sd->brightness = tot >> 2; - break; - default: -/* case Rev012A: */ - /* no way to read sensor settings */ - break; - } + tot = 0; + reg_r(gspca_dev, 0x8611, 1); + tot += gspca_dev->usb_buf[0]; + reg_r(gspca_dev, 0x8612, 1); + tot += gspca_dev->usb_buf[0]; + reg_r(gspca_dev, 0x8613, 1); + tot += gspca_dev->usb_buf[0]; + reg_r(gspca_dev, 0x8614, 1); + tot += gspca_dev->usb_buf[0]; + sd->brightness = tot >> 2; } +/* rev72a only */ static void getcontrast(struct gspca_dev *gspca_dev) { struct sd *sd = (struct sd *) gspca_dev; __u16 tot; - switch (sd->chip_revision) { - case Rev072A: - tot = 0; - reg_r(gspca_dev, 0x8651, 1); - tot += gspca_dev->usb_buf[0]; - reg_r(gspca_dev, 0x8652, 1); - tot += gspca_dev->usb_buf[0]; - reg_r(gspca_dev, 0x8653, 1); - tot += gspca_dev->usb_buf[0]; - reg_r(gspca_dev, 0x8654, 1); - tot += gspca_dev->usb_buf[0]; - sd->contrast = tot << 6; - break; - default: -/* case Rev012A: */ - /* no way to read sensor settings */ - break; - } + tot = 0; + reg_r(gspca_dev, 0x8651, 1); + tot += gspca_dev->usb_buf[0]; + reg_r(gspca_dev, 0x8652, 1); + tot += gspca_dev->usb_buf[0]; + reg_r(gspca_dev, 0x8653, 1); + tot += gspca_dev->usb_buf[0]; + reg_r(gspca_dev, 0x8654, 1); + tot += gspca_dev->usb_buf[0]; + sd->contrast = tot << 6; PDEBUG(D_CONF, "get contrast %d", sd->contrast); } +/* rev 72a only */ static int sd_setbrightness(struct gspca_dev *gspca_dev, __s32 val) { struct sd *sd = (struct sd *) gspca_dev; @@ -985,6 +905,7 @@ static int sd_getbrightness(struct gspca_dev *gspca_dev, __s32 *val) return 0; } +/* rev 72a only */ static int sd_setcontrast(struct gspca_dev *gspca_dev, __s32 val) { struct sd *sd = (struct sd *) gspca_dev; @@ -1022,7 +943,7 @@ static int sd_getautogain(struct gspca_dev *gspca_dev, __s32 *val) return 0; } -/* white balance - new */ +/* rev12a only */ static int sd_setwhite(struct gspca_dev *gspca_dev, __s32 val) { struct sd *sd = (struct sd *) gspca_dev; @@ -1041,20 +962,173 @@ static int sd_getwhite(struct gspca_dev *gspca_dev, __s32 *val) return 0; } +/* rev12a only */ +static int sd_setexposure(struct gspca_dev *gspca_dev, __s32 val) +{ + struct sd *sd = (struct sd *) gspca_dev; + + sd->exposure = val; + if (gspca_dev->streaming) + setexposure(gspca_dev); + return 0; +} + +static int sd_getexposure(struct gspca_dev *gspca_dev, __s32 *val) +{ + struct sd *sd = (struct sd *) gspca_dev; + + *val = sd->exposure; + return 0; +} + +/* rev12a only */ +static int sd_setgain(struct gspca_dev *gspca_dev, __s32 val) +{ + struct sd *sd = (struct sd *) gspca_dev; + + sd->gain = val; + if (gspca_dev->streaming) + setgain(gspca_dev); + return 0; +} + +static int sd_getgain(struct gspca_dev *gspca_dev, __s32 *val) +{ + struct sd *sd = (struct sd *) gspca_dev; + + *val = sd->gain; + return 0; +} + +/* control tables */ +static struct ctrl sd_ctrls_12a[] = { + { + { + .id = V4L2_CID_DO_WHITE_BALANCE, + .type = V4L2_CTRL_TYPE_INTEGER, + .name = "While Balance", + .minimum = WHITE_MIN, + .maximum = WHITE_MAX, + .step = 1, + .default_value = WHITE_DEF, + }, + .set = sd_setwhite, + .get = sd_getwhite, + }, + { + { + .id = V4L2_CID_EXPOSURE, + .type = V4L2_CTRL_TYPE_INTEGER, + .name = "Exposure", + .minimum = EXPOSURE_MIN, + .maximum = EXPOSURE_MAX, + .step = 1, + .default_value = EXPOSURE_DEF, + }, + .set = sd_setexposure, + .get = sd_getexposure, + }, + { + { + .id = V4L2_CID_AUTOGAIN, + .type = V4L2_CTRL_TYPE_BOOLEAN, + .name = "Auto Gain", + .minimum = AUTOGAIN_MIN, + .maximum = AUTOGAIN_MAX, + .step = 1, + .default_value = AUTOGAIN_DEF, + }, + .set = sd_setautogain, + .get = sd_getautogain, + }, + { + { + .id = V4L2_CID_GAIN, + .type = V4L2_CTRL_TYPE_INTEGER, + .name = "Gain", + .minimum = GAIN_MIN, + .maximum = GAIN_MAX, + .step = 1, + .default_value = GAIN_DEF, + }, + .set = sd_setgain, + .get = sd_getgain, + }, +}; + +static struct ctrl sd_ctrls_72a[] = { + { + { + .id = V4L2_CID_BRIGHTNESS, + .type = V4L2_CTRL_TYPE_INTEGER, + .name = "Brightness", + .minimum = BRIGHTNESS_MIN, + .maximum = BRIGHTNESS_MAX, + .step = 1, + .default_value = BRIGHTNESS_DEF, + }, + .set = sd_setbrightness, + .get = sd_getbrightness, + }, + { + { + .id = V4L2_CID_CONTRAST, + .type = V4L2_CTRL_TYPE_INTEGER, + .name = "Contrast", + .minimum = CONTRAST_MIN, + .maximum = CONTRAST_MAX, + .step = 1, + .default_value = CONTRAST_DEF, + }, + .set = sd_setcontrast, + .get = sd_getcontrast, + }, + { + { + .id = V4L2_CID_AUTOGAIN, + .type = V4L2_CTRL_TYPE_BOOLEAN, + .name = "Auto Gain", + .minimum = AUTOGAIN_MIN, + .maximum = AUTOGAIN_MAX, + .step = 1, + .default_value = AUTOGAIN_DEF, + }, + .set = sd_setautogain, + .get = sd_getautogain, + }, +}; + /* sub-driver description */ -static const struct sd_desc sd_desc = { +static const struct sd_desc sd_desc_12a = { .name = MODULE_NAME, - .ctrls = sd_ctrls, - .nctrls = ARRAY_SIZE(sd_ctrls), + .ctrls = sd_ctrls_12a, + .nctrls = ARRAY_SIZE(sd_ctrls_12a), .config = sd_config, - .open = sd_open, - .start = sd_start, + .open = sd_open_12a, + .start = sd_start_12a, + .stopN = sd_stopN, + .stop0 = sd_stop0, + .close = sd_close, + .pkt_scan = sd_pkt_scan, +/* .dq_callback = do_autogain, * fixme */ +}; +static const struct sd_desc sd_desc_72a = { + .name = MODULE_NAME, + .ctrls = sd_ctrls_72a, + .nctrls = ARRAY_SIZE(sd_ctrls_72a), + .config = sd_config, + .open = sd_open_72a, + .start = sd_start_72a, .stopN = sd_stopN, .stop0 = sd_stop0, .close = sd_close, .pkt_scan = sd_pkt_scan, .dq_callback = do_autogain, }; +static const struct sd_desc *sd_desc[2] = { + &sd_desc_12a, + &sd_desc_72a +}; /* -- module initialisation -- */ static const __devinitdata struct usb_device_id device_table[] = { @@ -1082,7 +1156,9 @@ MODULE_DEVICE_TABLE(usb, device_table); static int sd_probe(struct usb_interface *intf, const struct usb_device_id *id) { - return gspca_dev_probe(intf, id, &sd_desc, sizeof(struct sd), + return gspca_dev_probe(intf, id, + sd_desc[id->driver_info], + sizeof(struct sd), THIS_MODULE); } -- cgit v0.10.2 From 285a4f6c8e518f03758c7b085bda13bb3795df0a Mon Sep 17 00:00:00 2001 From: Jean-Francois Moine Date: Wed, 3 Sep 2008 16:47:33 -0300 Subject: V4L/DVB (8673): gspca: Bad frame scanning again and bad init in pac7311. Signed-off-by: Jean-Francois Moine Signed-off-by: Mauro Carvalho Chehab diff --git a/drivers/media/video/gspca/pac7311.c b/drivers/media/video/gspca/pac7311.c index 730b4a1..85d9ddb 100644 --- a/drivers/media/video/gspca/pac7311.c +++ b/drivers/media/video/gspca/pac7311.c @@ -220,6 +220,7 @@ static const __u8 probe_7302[] = { }; static const __u8 start_7302[] = { /* index, len, [value]* */ + 0xff, 1, 0x00, /* page 0 */ 0x00, 12, 0x01, 0x40, 0x40, 0x40, 0x01, 0xe0, 0x02, 0x80, 0x00, 0x00, 0x00, 0x00, 0x0d, 24, 0x03, 0x01, 0x00, 0xb5, 0x07, 0xcb, 0x00, 0x00, @@ -249,7 +250,7 @@ static const __u8 start_7302[] = { 0xd1, 11, 0x01, 0x30, 0x49, 0x5e, 0x6f, 0x7f, 0x8e, 0xa9, 0xc1, 0xd7, 0xec, 0xdc, 1, 0x01, - 0xff, 1, 0x01, + 0xff, 1, 0x01, /* page 1 */ 0x12, 3, 0x02, 0x00, 0x01, 0x3e, 2, 0x00, 0x00, 0x76, 5, 0x01, 0x20, 0x40, 0x00, 0xf2, @@ -257,26 +258,26 @@ static const __u8 start_7302[] = { 0x7f, 10, 0x4b, 0x0f, 0x01, 0x2c, 0x02, 0x58, 0x03, 0x20, 0x02, 0x00, 0x96, 5, 0x01, 0x10, 0x04, 0x01, 0x04, - 0xc8, 17, 0x00, 0x00, 0x00, 0x00, 0x00, 0x07, 0x00, 0x00, + 0xc8, 14, 0x00, 0x00, 0x00, 0x00, 0x00, 0x07, 0x00, 0x00, 0x07, 0x00, 0x01, 0x07, 0x04, 0x01, - 0x01, + 0xd8, 1, 0x01, 0xdb, 2, 0x00, 0x01, - 0xde, 8, 0x00, 0x01, 0x04, 0x04, 0x00, 0x00, 0x00, + 0xde, 7, 0x00, 0x01, 0x04, 0x04, 0x00, 0x00, 0x00, 0xe6, 4, 0x00, 0x00, 0x00, 0x01, 0xeb, 1, 0x00, - 0xff, 1, 0x02, + 0xff, 1, 0x02, /* page 2 */ 0x22, 1, 0x00, - 0xff, 1, 0x03, + 0xff, 1, 0x03, /* page 3 */ 0x00, 255, /* load the page 3 */ 0x11, 1, 0x01, - 0xff, 1, 0x02, + 0xff, 1, 0x02, /* page 2 */ 0x13, 1, 0x00, 0x22, 4, 0x1f, 0xa4, 0xf0, 0x96, 0x27, 2, 0x14, 0x0c, 0x2a, 5, 0xc8, 0x00, 0x18, 0x12, 0x22, 0x64, 8, 0x00, 0x00, 0xf0, 0x01, 0x14, 0x44, 0x44, 0x44, 0x6e, 1, 0x08, - 0xff, 1, 0x03, + 0xff, 1, 0x03, /* page 1 */ 0x78, 1, 0x00, 0, 0 /* end of sequence */ }; @@ -321,14 +322,14 @@ static const __u8 probe_7311[] = { static const __u8 start_7311[] = { /* index, len, [value]* */ - 0xff, 1, 0x01, - 0x02, 53, 0x48, 0x0a, 0x40, 0x08, 0x00, 0x00, 0x08, 0x00, + 0xff, 1, 0x01, /* page 1 */ + 0x02, 43, 0x48, 0x0a, 0x40, 0x08, 0x00, 0x00, 0x08, 0x00, 0x06, 0xff, 0x11, 0xff, 0x5a, 0x30, 0x90, 0x4c, 0x00, 0x07, 0x00, 0x0a, 0x10, 0x00, 0xa0, 0x10, 0x02, 0x00, 0x00, 0x00, 0x00, 0x0b, 0x01, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x3e, 52, 0x00, 0x00, 0x78, 0x52, 0x4a, 0x52, 0x78, 0x6e, + 0x3e, 42, 0x00, 0x00, 0x78, 0x52, 0x4a, 0x52, 0x78, 0x6e, 0x48, 0x46, 0x48, 0x6e, 0x5f, 0x49, 0x42, 0x49, 0x5f, 0x5f, 0x49, 0x42, 0x49, 0x5f, 0x6e, 0x48, 0x46, 0x48, 0x6e, 0x78, 0x52, 0x4a, 0x52, 0x78, @@ -342,7 +343,7 @@ static const __u8 start_7311[] = { 0xa0, 4, 0x44, 0x44, 0x44, 0x04, 0xf0, 13, 0x01, 0x00, 0x00, 0x00, 0x22, 0x00, 0x20, 0x00, 0x3f, 0x00, 0x0a, 0x01, 0x00, - 0xff, 1, 0x04, + 0xff, 1, 0x04, /* page 4 */ 0x00, 254, /* load the page 4 */ 0x11, 1, 0x01, 0, 0 /* end of sequence */ @@ -738,6 +739,24 @@ static void sd_pkt_scan(struct gspca_dev *gspca_dev, #define INTER_FRAME 0x53 /* eof + inter frame + sof */ #define LUM_OFFSET 0x1e /* reverse offset / start of frame */ +/*fixme:test+*/ +/* dump the packet */ + if (gspca_debug & 0x200) { + static char tmp[50]; + + PDEBUG(0x200, "pkt_scan"); + tmp[0] = 0; + for (i = 0; i < len; i++) { + if (i % 16 == 0 && i != 0) { + PDEBUG(0x200, "%s", tmp); + tmp[0] = 0; + } + sprintf(&tmp[(i % 16) * 3], "%02x ", data[i]); + } + if (tmp[0] != 0) + PDEBUG(0x200, "%s", tmp); + } +/*fixme:test-*/ /* * inside a frame, there may be: * escaped ff ('ff 00') @@ -819,6 +838,25 @@ static void sd_pkt_scan(struct gspca_dev *gspca_dev, put_jpeg_head(gspca_dev, frame); break; case 0xff: /* 'ff ff ff xx' */ +/*fixme:test+*/ +/* is there a start of frame ? */ + if (data[i + 2] == 0x00) { + static __u8 ffd9[2] = {0xff, 0xd9}; + + gspca_frame_add(gspca_dev, + INTER_PACKET, + frame, data, + i + 7 - INTER_FRAME); + frame = gspca_frame_add(gspca_dev, + LAST_PACKET, + frame, ffd9, 2); + data += i + 7; + len -= i + 7; + i = 0; + put_jpeg_head(gspca_dev, frame); + break; + } +/*fixme:test-*/ gspca_frame_add(gspca_dev, INTER_PACKET, frame, data, i); data += i + 4; -- cgit v0.10.2 From 6ab0b174d22b448d66058c9de0114fdfac5b7ccf Mon Sep 17 00:00:00 2001 From: Jean-Francois Moine Date: Wed, 3 Sep 2008 16:47:34 -0300 Subject: V4L/DVB (8674): gspca: Webcam 0c45:612e added in sonixj. Signed-off-by: Jean-Francois Moine Signed-off-by: Mauro Carvalho Chehab diff --git a/drivers/media/video/gspca/sonixj.c b/drivers/media/video/gspca/sonixj.c index 0a20db8..47737bf 100644 --- a/drivers/media/video/gspca/sonixj.c +++ b/drivers/media/video/gspca/sonixj.c @@ -55,8 +55,9 @@ struct sd { #define SENSOR_MI0360 1 #define SENSOR_MO4000 2 #define SENSOR_OM6802 3 -#define SENSOR_OV7648 4 -#define SENSOR_OV7660 5 +#define SENSOR_OV7630 4 +#define SENSOR_OV7648 5 +#define SENSOR_OV7660 6 unsigned char i2c_base; }; @@ -195,6 +196,17 @@ static const __u8 sn_om6802[] = { 0xf7 }; +static const __u8 sn_ov7630[] = { +/* reg0 reg1 reg2 reg3 reg4 reg5 reg6 reg7 */ + 0x00, 0x21, 0x40, 0x00, 0x1a, 0x20, 0x1f, 0x20, +/* reg8 reg9 rega regb regc regd rege regf */ + 0xa1, 0x21, 0x76, 0x21, 0x00, 0x00, 0x00, 0x10, +/* reg10 reg11 reg12 reg13 reg14 reg15 reg16 reg17 */ + 0x03, 0x00, 0x04, 0x01, 0x0a, 0x28, 0x1e, 0xc2, +/* reg18 reg19 reg1a reg1b reg1c reg1d reg1e reg1f */ + 0x0b, 0x00, 0x00, 0x00, 0x00, 0x00 +}; + static const __u8 sn_ov7648[] = { /* reg0 reg1 reg2 reg3 reg4 reg5 reg6 reg7 */ 0x00, 0x21, 0x62, 0x00, 0x1a, 0x20, 0x20, 0x20, @@ -223,6 +235,7 @@ static const __u8 *sn_tb[] = { sn_mi0360, sn_mo4000, sn_om6802, + sn_ov7630, sn_ov7648, sn_ov7660 }; @@ -390,6 +403,56 @@ static __u8 om6802_sensor_init[][8] = { /* {0xa0, 0x34, 0x69, 0x01, 0x00, 0x00, 0x00, 0x10}, */ {} }; +static const __u8 ov7630_sensor_init[][8] = { + {0xa1, 0x21, 0x76, 0x01, 0x00, 0x00, 0x00, 0x10}, + {0xa1, 0x21, 0x12, 0xc8, 0x00, 0x00, 0x00, 0x10}, +/* win: delay 20ms */ + {0xa1, 0x21, 0x12, 0x48, 0x00, 0x00, 0x00, 0x10}, + {0xa1, 0x21, 0x12, 0xc8, 0x00, 0x00, 0x00, 0x10}, +/* win: delay 20ms */ + {0xa1, 0x21, 0x12, 0x48, 0x00, 0x00, 0x00, 0x10}, +/* win: loop on 2 wwrite, 1 read */ + {0xd1, 0x21, 0x03, 0x80, 0x10, 0x20, 0x80, 0x10}, + {0xb1, 0x21, 0x0c, 0x20, 0x20, 0x00, 0x00, 0x10}, + {0xd1, 0x21, 0x11, 0x00, 0x48, 0xc0, 0x00, 0x10}, + {0xb1, 0x21, 0x15, 0x80, 0x03, 0x00, 0x00, 0x10}, + {0xd1, 0x21, 0x17, 0x1b, 0xbd, 0x05, 0xf6, 0x10}, + {0xa1, 0x21, 0x1b, 0x04, 0x00, 0x00, 0x00, 0x10}, + {0xd1, 0x21, 0x1f, 0x00, 0x80, 0x80, 0x80, 0x10}, + {0xd1, 0x21, 0x23, 0xde, 0x10, 0x8a, 0xa0, 0x10}, + {0xc1, 0x21, 0x27, 0xca, 0xa2, 0x74, 0x00, 0x10}, + {0xd1, 0x21, 0x2a, 0x88, 0x00, 0x88, 0x01, 0x10}, + {0xc1, 0x21, 0x2e, 0x80, 0x00, 0x18, 0x00, 0x10}, + {0xa1, 0x21, 0x21, 0x08, 0x00, 0x00, 0x00, 0x10}, + {0xa1, 0x21, 0x22, 0x00, 0x00, 0x00, 0x00, 0x10}, + {0xa1, 0x21, 0x2e, 0x00, 0x00, 0x00, 0x00, 0x10}, + {0xb1, 0x21, 0x32, 0xc2, 0x08, 0x00, 0x00, 0x10}, + {0xb1, 0x21, 0x4c, 0x00, 0x00, 0x00, 0x00, 0x10}, + {0xd1, 0x21, 0x60, 0x05, 0x40, 0x12, 0x57, 0x10}, + {0xa1, 0x21, 0x64, 0x73, 0x00, 0x00, 0x00, 0x10}, + {0xd1, 0x21, 0x65, 0x00, 0x55, 0x01, 0xac, 0x10}, + {0xa1, 0x21, 0x69, 0x38, 0x00, 0x00, 0x00, 0x10}, + {0xd1, 0x21, 0x6f, 0x1f, 0x01, 0x00, 0x10, 0x10}, + {0xd1, 0x21, 0x73, 0x50, 0x20, 0x02, 0x01, 0x10}, + {0xd1, 0x21, 0x77, 0xf3, 0x90, 0x98, 0x98, 0x10}, + {0xc1, 0x21, 0x7b, 0x00, 0x4c, 0xf7, 0x00, 0x10}, + {0xd1, 0x21, 0x17, 0x1b, 0xbd, 0x05, 0xf6, 0x10}, + {0xa1, 0x21, 0x1b, 0x04, 0x00, 0x00, 0x00, 0x10}, +/* */ + {0xa1, 0x21, 0x12, 0x48, 0x00, 0x00, 0x00, 0x10}, + {0xa1, 0x21, 0x12, 0x48, 0x00, 0x00, 0x00, 0x10}, +/*fixme: + 0x12, 0x04*/ + {0xa1, 0x21, 0x75, 0x82, 0x00, 0x00, 0x00, 0x10}, + {0xa1, 0x21, 0x10, 0x32, 0x00, 0x00, 0x00, 0x10}, + {0xa1, 0x21, 0x00, 0x00, 0x00, 0x00, 0x00, 0x10}, + {0xb1, 0x21, 0x01, 0x80, 0x80, 0x00, 0x00, 0x10}, + {0xa1, 0x21, 0x11, 0x00, 0x00, 0x00, 0x00, 0x10}, + {0xa1, 0x21, 0x2a, 0x88, 0x00, 0x00, 0x00, 0x10}, + {0xa1, 0x21, 0x2b, 0x34, 0x00, 0x00, 0x00, 0x10}, + {0xa1, 0x21, 0x10, 0x83, 0x00, 0x00, 0x00, 0x10}, + {0xb1, 0x21, 0x01, 0x88, 0x70, 0x00, 0x00, 0x10}, + {} +}; static const __u8 ov7660_sensor_init[][8] = { {0xa1, 0x21, 0x12, 0x80, 0x00, 0x00, 0x00, 0x10}, /* reset SCCB */ /* (delay 20ms) */ @@ -803,6 +866,19 @@ static void om6802_InitSensor(struct gspca_dev *gspca_dev) } } +static void ov7630_InitSensor(struct gspca_dev *gspca_dev) +{ + int i = 0; + + i2c_w8(gspca_dev, ov7630_sensor_init[i]); + i++; + msleep(20); + while (ov7630_sensor_init[i][0]) { + i2c_w8(gspca_dev, ov7630_sensor_init[i]); + i++; + } +} + static void ov7648_InitSensor(struct gspca_dev *gspca_dev) { int i = 0; @@ -1060,8 +1136,8 @@ static void sd_start(struct gspca_dev *gspca_dev) static const __u8 C0[] = { 0x2d, 0x2d, 0x3a, 0x05, 0x04, 0x3f }; static const __u8 CA[] = { 0x28, 0xd8, 0x14, 0xec }; static const __u8 CE[] = { 0x32, 0xdd, 0x2d, 0xdd }; /* MI0360 */ - static const __u8 CE_sn9c325[] = - { 0x32, 0xdd, 0x32, 0xdd }; /* OV7648 - SN9C325 */ + static const __u8 CE_ov76xx[] = + { 0x32, 0xdd, 0x32, 0xdd }; /* OV7630/48 */ sn9c1xx = sn_tb[(int) sd->sensor]; configure_gpio(gspca_dev, sn9c1xx); @@ -1079,10 +1155,17 @@ static void sd_start(struct gspca_dev *gspca_dev) reg_w1(gspca_dev, 0xc8, 0x50); reg_w1(gspca_dev, 0xc9, 0x3c); reg_w1(gspca_dev, 0x18, sn9c1xx[0x18]); - switch (sd->bridge) { - case BRIDGE_SN9C325: + switch (sd->sensor) { + case SENSOR_OV7630: + reg17 = 0xe2; + break; + case SENSOR_OV7648: reg17 = 0xae; break; +/*jfm: from win trace */ + case SENSOR_OV7660: + reg17 = 0xa0; + break; default: reg17 = 0x60; break; @@ -1138,6 +1221,11 @@ static void sd_start(struct gspca_dev *gspca_dev) om6802_InitSensor(gspca_dev); reg17 = 0x64; /* 640 MCKSIZE */ break; + case SENSOR_OV7630: + ov7630_InitSensor(gspca_dev); + reg17 = 0xe2; + reg1 = 0x40; + break; case SENSOR_OV7648: ov7648_InitSensor(gspca_dev); reg17 = 0xa2; @@ -1162,9 +1250,10 @@ static void sd_start(struct gspca_dev *gspca_dev) } reg_w(gspca_dev, 0xc0, C0, 6); reg_w(gspca_dev, 0xca, CA, 4); - switch (sd->bridge) { - case BRIDGE_SN9C325: - reg_w(gspca_dev, 0xce, CE_sn9c325, 4); + switch (sd->sensor) { + case SENSOR_OV7630: + case SENSOR_OV7648: + reg_w(gspca_dev, 0xce, CE_ov76xx, 4); break; default: reg_w(gspca_dev, 0xce, CE, 4); @@ -1208,6 +1297,7 @@ static void sd_stopN(struct gspca_dev *gspca_dev) i2c_w8(gspca_dev, stopmi0360); data = 0x29; break; + case SENSOR_OV7630: case SENSOR_OV7648: data = 0x29; break; @@ -1503,7 +1593,7 @@ static const __devinitdata struct usb_device_id device_table[] = { /*bw600.inf:*/ {USB_DEVICE(0x0c45, 0x612a), BSI(SN9C110, OV7648, 0x21)}, /*sn9c325?*/ {USB_DEVICE(0x0c45, 0x612c), BSI(SN9C110, MO4000, 0x21)}, -/* {USB_DEVICE(0x0c45, 0x612e), BSI(SN9C110, OV7630, 0x??)}, */ + {USB_DEVICE(0x0c45, 0x612e), BSI(SN9C110, OV7630, 0x21)}, /* {USB_DEVICE(0x0c45, 0x612f), BSI(SN9C110, ICM105C, 0x??)}, */ #ifndef CONFIG_USB_SN9C102 {USB_DEVICE(0x0c45, 0x6130), BSI(SN9C120, MI0360, 0x5d)}, -- cgit v0.10.2 From f75c4950bb6e677e89479192b2ecfbec0beab14e Mon Sep 17 00:00:00 2001 From: Jean-Francois Moine Date: Wed, 3 Sep 2008 16:47:35 -0300 Subject: V4L/DVB (8675): gspca: Pixmap PJPG (Pixart 73xx JPEG) added, generated by pac7311. The JPEG frames generated by the Pixart 73xx have: - special markers 'ff ff ff xx' every 1024/512 bytes, - unused 8 bits at end of JPEG blocks, and then ask for a new pixel format. Signed-off-by: Jean-Francois Moine Signed-off-by: Mauro Carvalho Chehab diff --git a/drivers/media/video/gspca/pac7311.c b/drivers/media/video/gspca/pac7311.c index 85d9ddb..3c9f2b1 100644 --- a/drivers/media/video/gspca/pac7311.c +++ b/drivers/media/video/gspca/pac7311.c @@ -22,6 +22,7 @@ #define MODULE_NAME "pac7311" #include "gspca.h" +#include "jpeg.h" MODULE_AUTHOR("Thomas Kaiser thomas@kaiser-linux.li"); MODULE_DESCRIPTION("Pixart PAC7311"); @@ -40,7 +41,6 @@ struct sd { unsigned char colors; unsigned char autogain; - char ffnb; /* number of 'ff' in the previous frame */ char tosof; /* number of bytes before next start of frame */ signed char ag_cnt; #define AG_CNT_START 13 @@ -121,95 +121,23 @@ static struct ctrl sd_ctrls[] = { }; static struct v4l2_pix_format vga_mode[] = { - {160, 120, V4L2_PIX_FMT_JPEG, V4L2_FIELD_NONE, + {160, 120, V4L2_PIX_FMT_PJPG, V4L2_FIELD_NONE, .bytesperline = 160, .sizeimage = 160 * 120 * 3 / 8 + 590, .colorspace = V4L2_COLORSPACE_JPEG, .priv = 2}, - {320, 240, V4L2_PIX_FMT_JPEG, V4L2_FIELD_NONE, + {320, 240, V4L2_PIX_FMT_PJPG, V4L2_FIELD_NONE, .bytesperline = 320, .sizeimage = 320 * 240 * 3 / 8 + 590, .colorspace = V4L2_COLORSPACE_JPEG, .priv = 1}, - {640, 480, V4L2_PIX_FMT_JPEG, V4L2_FIELD_NONE, + {640, 480, V4L2_PIX_FMT_PJPG, V4L2_FIELD_NONE, .bytesperline = 640, .sizeimage = 640 * 480 * 3 / 8 + 590, .colorspace = V4L2_COLORSPACE_JPEG, .priv = 0}, }; -#define PAC7311_JPEG_HEADER_SIZE (sizeof pac7311_jpeg_header) /* (594) */ - -static const __u8 pac7311_jpeg_header[] = { - 0xff, 0xd8, - 0xff, 0xe0, 0x00, 0x03, 0x20, - 0xff, 0xc0, 0x00, 0x11, 0x08, - 0x01, 0xe0, /* 12: height */ - 0x02, 0x80, /* 14: width */ - 0x03, /* 16 */ - 0x01, 0x21, 0x00, - 0x02, 0x11, 0x01, - 0x03, 0x11, 0x01, - 0xff, 0xdb, 0x00, 0x84, - 0x00, 0x10, 0x0b, 0x0c, 0x0e, 0x0c, 0x0a, 0x10, 0x0e, 0x0d, - 0x0e, 0x12, 0x11, 0x10, 0x13, 0x18, 0x28, 0x1a, 0x18, 0x16, - 0x16, 0x18, 0x31, 0x23, 0x25, 0x1d, 0x28, 0x3a, 0x33, 0x3d, - 0x3c, 0x39, 0x33, 0x38, 0x37, 0x40, 0x48, 0x5c, 0x4e, 0x40, - 0x44, 0x57, 0x45, 0x37, 0x38, 0x50, 0x6d, 0x51, 0x57, 0x5f, - 0x62, 0x67, 0x68, 0x67, 0x3e, 0x4d, 0x71, 0x79, 0x70, 0x64, - 0x78, 0x5c, 0x65, 0x67, 0x63, 0x01, 0x11, 0x12, 0x12, 0x18, - 0x15, 0x18, 0x2f, 0x1a, 0x1a, 0x2f, 0x63, 0x42, 0x38, 0x42, - 0x63, 0x63, 0x63, 0x63, 0x63, 0x63, 0x63, 0x63, 0x63, 0x63, - 0x63, 0x63, 0x63, 0x63, 0x63, 0x63, 0x63, 0x63, 0x63, 0x63, - 0x63, 0x63, 0x63, 0x63, 0x63, 0x63, 0x63, 0x63, 0x63, 0x63, - 0x63, 0x63, 0x63, 0x63, 0x63, 0x63, 0x63, 0x63, 0x63, 0x63, - 0x63, 0x63, 0x63, 0x63, 0x63, 0x63, 0x63, 0x63, 0x63, 0x63, - 0xff, 0xc4, 0x01, 0xa2, 0x00, 0x00, 0x01, 0x05, 0x01, 0x01, - 0x01, 0x01, 0x01, 0x01, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x07, 0x08, - 0x09, 0x0a, 0x0b, 0x10, 0x00, 0x02, 0x01, 0x03, 0x03, 0x02, - 0x04, 0x03, 0x05, 0x05, 0x04, 0x04, 0x00, 0x00, 0x01, 0x7d, - 0x01, 0x02, 0x03, 0x00, 0x04, 0x11, 0x05, 0x12, 0x21, 0x31, - 0x41, 0x06, 0x13, 0x51, 0x61, 0x07, 0x22, 0x71, 0x14, 0x32, - 0x81, 0x91, 0xa1, 0x08, 0x23, 0x42, 0xb1, 0xc1, 0x15, 0x52, - 0xd1, 0xf0, 0x24, 0x33, 0x62, 0x72, 0x82, 0x09, 0x0a, 0x16, - 0x17, 0x18, 0x19, 0x1a, 0x25, 0x26, 0x27, 0x28, 0x29, 0x2a, - 0x34, 0x35, 0x36, 0x37, 0x38, 0x39, 0x3a, 0x43, 0x44, 0x45, - 0x46, 0x47, 0x48, 0x49, 0x4a, 0x53, 0x54, 0x55, 0x56, 0x57, - 0x58, 0x59, 0x5a, 0x63, 0x64, 0x65, 0x66, 0x67, 0x68, 0x69, - 0x6a, 0x73, 0x74, 0x75, 0x76, 0x77, 0x78, 0x79, 0x7a, 0x83, - 0x84, 0x85, 0x86, 0x87, 0x88, 0x89, 0x8a, 0x92, 0x93, 0x94, - 0x95, 0x96, 0x97, 0x98, 0x99, 0x9a, 0xa2, 0xa3, 0xa4, 0xa5, - 0xa6, 0xa7, 0xa8, 0xa9, 0xaa, 0xb2, 0xb3, 0xb4, 0xb5, 0xb6, - 0xb7, 0xb8, 0xb9, 0xba, 0xc2, 0xc3, 0xc4, 0xc5, 0xc6, 0xc7, - 0xc8, 0xc9, 0xca, 0xd2, 0xd3, 0xd4, 0xd5, 0xd6, 0xd7, 0xd8, - 0xd9, 0xda, 0xe1, 0xe2, 0xe3, 0xe4, 0xe5, 0xe6, 0xe7, 0xe8, - 0xe9, 0xea, 0xf1, 0xf2, 0xf3, 0xf4, 0xf5, 0xf6, 0xf7, 0xf8, - 0xf9, 0xfa, 0x01, 0x00, 0x03, 0x01, 0x01, 0x01, 0x01, 0x01, - 0x01, 0x01, 0x01, 0x01, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x07, 0x08, 0x09, 0x0a, - 0x0b, 0x11, 0x00, 0x02, 0x01, 0x02, 0x04, 0x04, 0x03, 0x04, - 0x07, 0x05, 0x04, 0x04, 0x00, 0x01, 0x02, 0x77, 0x00, 0x01, - 0x02, 0x03, 0x11, 0x04, 0x05, 0x21, 0x31, 0x06, 0x12, 0x41, - 0x51, 0x07, 0x61, 0x71, 0x13, 0x22, 0x32, 0x81, 0x08, 0x14, - 0x42, 0x91, 0xa1, 0xb1, 0xc1, 0x09, 0x23, 0x33, 0x52, 0xf0, - 0x15, 0x62, 0x72, 0xd1, 0x0a, 0x16, 0x24, 0x34, 0xe1, 0x25, - 0xf1, 0x17, 0x18, 0x19, 0x1a, 0x26, 0x27, 0x28, 0x29, 0x2a, - 0x35, 0x36, 0x37, 0x38, 0x39, 0x3a, 0x43, 0x44, 0x45, 0x46, - 0x47, 0x48, 0x49, 0x4a, 0x53, 0x54, 0x55, 0x56, 0x57, 0x58, - 0x59, 0x5a, 0x63, 0x64, 0x65, 0x66, 0x67, 0x68, 0x69, 0x6a, - 0x73, 0x74, 0x75, 0x76, 0x77, 0x78, 0x79, 0x7a, 0x82, 0x83, - 0x84, 0x85, 0x86, 0x87, 0x88, 0x89, 0x8a, 0x92, 0x93, 0x94, - 0x95, 0x96, 0x97, 0x98, 0x99, 0x9a, 0xa2, 0xa3, 0xa4, 0xa5, - 0xa6, 0xa7, 0xa8, 0xa9, 0xaa, 0xb2, 0xb3, 0xb4, 0xb5, 0xb6, - 0xb7, 0xb8, 0xb9, 0xba, 0xc2, 0xc3, 0xc4, 0xc5, 0xc6, 0xc7, - 0xc8, 0xc9, 0xca, 0xd2, 0xd3, 0xd4, 0xd5, 0xd6, 0xd7, 0xd8, - 0xd9, 0xda, 0xe2, 0xe3, 0xe4, 0xe5, 0xe6, 0xe7, 0xe8, 0xe9, - 0xea, 0xf2, 0xf3, 0xf4, 0xf5, 0xf6, 0xf7, 0xf8, 0xf9, 0xfa, - 0xff, 0xda, 0x00, 0x0c, 0x03, 0x01, 0x00, 0x02, 0x11, 0x03, - 0x11, 0x00, 0x3f, 0x00 -}; - /* pac 7302 */ static const __u8 probe_7302[] = { /* index,value */ @@ -566,7 +494,6 @@ static void sd_start(struct gspca_dev *gspca_dev) { struct sd *sd = (struct sd *) gspca_dev; - sd->ffnb = 0; sd->tosof = 0; if (sd->sensor == SENSOR_PAC7302) @@ -699,34 +626,6 @@ static void do_autogain(struct gspca_dev *gspca_dev) } } -/* output the jpeg header */ -static void put_jpeg_head(struct gspca_dev *gspca_dev, - struct gspca_frame *frame) -{ - struct sd *sd = (struct sd *) gspca_dev; - unsigned char tmpbuf[4]; - - if (sd->ag_cnt >= 0) { - if (--sd->ag_cnt < 0) { - sd->ag_cnt = AG_CNT_START; - atomic_set(&sd->avg_lum, sd->lum_sum / AG_CNT_START); - atomic_set(&sd->do_gain, 1); - } - } - gspca_frame_add(gspca_dev, FIRST_PACKET, frame, - (__u8 *) pac7311_jpeg_header, - 12); - tmpbuf[0] = gspca_dev->height >> 8; - tmpbuf[1] = gspca_dev->height & 0xff; - tmpbuf[2] = gspca_dev->width >> 8; - tmpbuf[3] = gspca_dev->width & 0xff; - gspca_frame_add(gspca_dev, INTER_PACKET, frame, - tmpbuf, 4); - gspca_frame_add(gspca_dev, INTER_PACKET, frame, - (__u8 *) &pac7311_jpeg_header[16], - PAC7311_JPEG_HEADER_SIZE - 16); -} - /* this function is run at interrupt level */ static void sd_pkt_scan(struct gspca_dev *gspca_dev, struct gspca_frame *frame, /* target */ @@ -739,24 +638,6 @@ static void sd_pkt_scan(struct gspca_dev *gspca_dev, #define INTER_FRAME 0x53 /* eof + inter frame + sof */ #define LUM_OFFSET 0x1e /* reverse offset / start of frame */ -/*fixme:test+*/ -/* dump the packet */ - if (gspca_debug & 0x200) { - static char tmp[50]; - - PDEBUG(0x200, "pkt_scan"); - tmp[0] = 0; - for (i = 0; i < len; i++) { - if (i % 16 == 0 && i != 0) { - PDEBUG(0x200, "%s", tmp); - tmp[0] = 0; - } - sprintf(&tmp[(i % 16) * 3], "%02x ", data[i]); - } - if (tmp[0] != 0) - PDEBUG(0x200, "%s", tmp); - } -/*fixme:test-*/ /* * inside a frame, there may be: * escaped ff ('ff 00') @@ -767,47 +648,10 @@ static void sd_pkt_scan(struct gspca_dev *gspca_dev, * 0x33 bytes * one byte luminosity * 0x16 bytes - * ff ff 00 ff 96 62 44 start of frame header + * ff ff 00 ff 96 62 44 start of frame */ - if (sd->tosof == 0) { /* if inside a frame */ - - /* check for 'ff ff ff xx' at start and at end of packet */ - /* (len is always >= 3 and xx never ff) */ - switch (sd->ffnb) { - case 1: - if (data[0] != 0xff) { /* can be '00' only */ - __u8 ff; - - sd->ffnb = 0; - ff = 0xff; - gspca_frame_add(gspca_dev, INTER_PACKET, - frame, &ff, 1); - break; /* keep 'ff 00' */ - } - /* fall thru */ - case 2: - case 3: - data += 4 - sd->ffnb; - len -= 4 - sd->ffnb; - sd->ffnb = 0; - break; - } - if (data[len - 1] == 0xff) { - if (data[len - 2] == 0xff) { - if (data[len - 3] == 0xff) { - sd->ffnb = 3; - len -= 3; - } else { - sd->ffnb = 2; - len -= 2; - } - } else { - sd->ffnb = 1; - len--; - } - } - } else { /* outside a frame */ + if (sd->tosof != 0) { /* if outside a frame */ /* get the luminosity and go to the start of frame */ data += sd->tosof; @@ -815,14 +659,14 @@ static void sd_pkt_scan(struct gspca_dev *gspca_dev, if (sd->tosof > LUM_OFFSET) sd->lum_sum += data[-LUM_OFFSET]; sd->tosof = 0; - put_jpeg_head(gspca_dev, frame); + jpeg_put_header(gspca_dev, frame, 1, 0x21); } for (i = 0; i < len; i++) { if (data[i] != 0xff) continue; switch (data[i + 1]) { - case 0xd9: /* end of frame */ + case 0xd9: /* 'ff d9' end of frame */ frame = gspca_frame_add(gspca_dev, LAST_PACKET, frame, data, i + 2); @@ -835,33 +679,7 @@ static void sd_pkt_scan(struct gspca_dev *gspca_dev, sd->tosof = -len; break; } - put_jpeg_head(gspca_dev, frame); - break; - case 0xff: /* 'ff ff ff xx' */ -/*fixme:test+*/ -/* is there a start of frame ? */ - if (data[i + 2] == 0x00) { - static __u8 ffd9[2] = {0xff, 0xd9}; - - gspca_frame_add(gspca_dev, - INTER_PACKET, - frame, data, - i + 7 - INTER_FRAME); - frame = gspca_frame_add(gspca_dev, - LAST_PACKET, - frame, ffd9, 2); - data += i + 7; - len -= i + 7; - i = 0; - put_jpeg_head(gspca_dev, frame); - break; - } -/*fixme:test-*/ - gspca_frame_add(gspca_dev, INTER_PACKET, - frame, data, i); - data += i + 4; - len -= i + 4; - i = 0; + jpeg_put_header(gspca_dev, frame, 1, 0x21); break; } } diff --git a/include/linux/videodev2.h b/include/linux/videodev2.h index e65a6be..6c73516 100644 --- a/include/linux/videodev2.h +++ b/include/linux/videodev2.h @@ -334,6 +334,7 @@ struct v4l2_pix_format { #define V4L2_PIX_FMT_SPCA508 v4l2_fourcc('S', '5', '0', '8') /* YUVY per line */ #define V4L2_PIX_FMT_SPCA561 v4l2_fourcc('S', '5', '6', '1') /* compressed GBRG bayer */ #define V4L2_PIX_FMT_PAC207 v4l2_fourcc('P', '2', '0', '7') /* compressed BGGR bayer */ +#define V4L2_PIX_FMT_PJPG v4l2_fourcc('P', 'J', 'P', 'G') /* Pixart 73xx JPEG */ /* * F O R M A T E N U M E R A T I O N -- cgit v0.10.2 From c7087f56a42b0aa82b181d9a08a376c4add7a683 Mon Sep 17 00:00:00 2001 From: Adrian Bunk Date: Wed, 3 Sep 2008 16:47:36 -0300 Subject: V4L/DVB (8678): Remove the dead CONFIG_RADIO_MIROPCM20{,_RDS} code The CONFIG_RADIO_MIROPCM20{,_RDS} code became dead code 1.5 years ago. Signed-off-by: Adrian Bunk Signed-off-by: Mauro Carvalho Chehab diff --git a/drivers/media/radio/Makefile b/drivers/media/radio/Makefile index a30159f..7ca71ab 100644 --- a/drivers/media/radio/Makefile +++ b/drivers/media/radio/Makefile @@ -2,8 +2,6 @@ # Makefile for the kernel character device drivers. # -miropcm20-objs := miropcm20-rds-core.o miropcm20-radio.o - obj-$(CONFIG_RADIO_AZTECH) += radio-aztech.o obj-$(CONFIG_RADIO_RTRACK2) += radio-rtrack2.o obj-$(CONFIG_RADIO_SF16FMI) += radio-sf16fmi.o @@ -14,8 +12,6 @@ obj-$(CONFIG_RADIO_TERRATEC) += radio-terratec.o obj-$(CONFIG_RADIO_MAXIRADIO) += radio-maxiradio.o obj-$(CONFIG_RADIO_RTRACK) += radio-aimslab.o obj-$(CONFIG_RADIO_ZOLTRIX) += radio-zoltrix.o -obj-$(CONFIG_RADIO_MIROPCM20) += miropcm20.o -obj-$(CONFIG_RADIO_MIROPCM20_RDS) += miropcm20-rds.o obj-$(CONFIG_RADIO_GEMTEK) += radio-gemtek.o obj-$(CONFIG_RADIO_GEMTEK_PCI) += radio-gemtek-pci.o obj-$(CONFIG_RADIO_TRUST) += radio-trust.o diff --git a/drivers/media/radio/miropcm20-radio.c b/drivers/media/radio/miropcm20-radio.c deleted file mode 100644 index 7fd7ee2..0000000 --- a/drivers/media/radio/miropcm20-radio.c +++ /dev/null @@ -1,266 +0,0 @@ -/* Miro PCM20 radio driver for Linux radio support - * (c) 1998 Ruurd Reitsma - * Thanks to Norberto Pellici for the ACI device interface specification - * The API part is based on the radiotrack driver by M. Kirkwood - * This driver relies on the aci mixer (drivers/sound/aci.c) - * Look there for further info... - */ - -/* Revision history: - * - * 1998 Ruurd Reitsma - * 2000-09-05 Robert Siemer - * removed unfinished volume control (maybe adding it later again) - * use OSS-mixer; added stereo control - */ - -/* What ever you think about the ACI, version 0x07 is not very well! - * I can't get frequency, 'tuner status', 'tuner flags' or mute/mono - * conditions... Robert - */ - -#include -#include -#include -#include -#include -#include "oss/aci.h" -#include "miropcm20-rds-core.h" - -static int radio_nr = -1; -module_param(radio_nr, int, 0); - -struct pcm20_device { - unsigned long freq; - int muted; - int stereo; -}; - - -static int pcm20_mute(struct pcm20_device *dev, unsigned char mute) -{ - dev->muted = mute; - return aci_write_cmd(ACI_SET_TUNERMUTE, mute); -} - -static int pcm20_stereo(struct pcm20_device *dev, unsigned char stereo) -{ - dev->stereo = stereo; - return aci_write_cmd(ACI_SET_TUNERMONO, !stereo); -} - -static int pcm20_setfreq(struct pcm20_device *dev, unsigned long freq) -{ - unsigned char freql; - unsigned char freqh; - - dev->freq=freq; - - freq /= 160; - if (!(aci_version==0x07 || aci_version>=0xb0)) - freq /= 10; /* I don't know exactly which version - * needs this hack */ - freql = freq & 0xff; - freqh = freq >> 8; - - aci_rds_cmd(RDS_RESET, NULL, 0); - pcm20_stereo(dev, 1); - - return aci_rw_cmd(ACI_WRITE_TUNE, freql, freqh); -} - -static int pcm20_getflags(struct pcm20_device *dev, __u32 *flags, __u16 *signal) -{ - /* okay, check for signal, stereo and rds here... */ - int i; - unsigned char buf; - - if ((i=aci_rw_cmd(ACI_READ_TUNERSTATION, -1, -1))<0) - return i; - pr_debug("check_sig: 0x%x\n", i); - if (i & 0x80) { - /* no signal from tuner */ - *flags=0; - *signal=0; - return 0; - } else - *signal=0xffff; - - if ((i=aci_rw_cmd(ACI_READ_TUNERSTEREO, -1, -1))<0) - return i; - if (i & 0x40) { - *flags=0; - } else { - /* stereo */ - *flags=VIDEO_TUNER_STEREO_ON; - /* I can't see stereo, when forced to mono */ - dev->stereo=1; - } - - if ((i=aci_rds_cmd(RDS_STATUS, &buf, 1))<0) - return i; - if (buf & 1) - /* RDS available */ - *flags|=VIDEO_TUNER_RDS_ON; - else - return 0; - - if ((i=aci_rds_cmd(RDS_RXVALUE, &buf, 1))<0) - return i; - pr_debug("rds-signal: %d\n", buf); - if (buf > 15) { - printk("miropcm20-radio: RX strengths unexpected high...\n"); - buf=15; - } - /* refine signal */ - if ((*signal=SCALE(15, 0xffff, buf))==0) - *signal = 1; - - return 0; -} - -static int pcm20_do_ioctl(struct inode *inode, struct file *file, - unsigned int cmd, void *arg) -{ - struct video_device *dev = video_devdata(file); - struct pcm20_device *pcm20 = dev->priv; - int i; - - switch(cmd) - { - case VIDIOCGCAP: - { - struct video_capability *v = arg; - memset(v,0,sizeof(*v)); - v->type=VID_TYPE_TUNER; - strcpy(v->name, "Miro PCM20"); - v->channels=1; - v->audios=1; - return 0; - } - case VIDIOCGTUNER: - { - struct video_tuner *v = arg; - if(v->tuner) /* Only 1 tuner */ - return -EINVAL; - v->rangelow=87*16000; - v->rangehigh=108*16000; - pcm20_getflags(pcm20, &v->flags, &v->signal); - v->flags|=VIDEO_TUNER_LOW; - v->mode=VIDEO_MODE_AUTO; - strcpy(v->name, "FM"); - return 0; - } - case VIDIOCSTUNER: - { - struct video_tuner *v = arg; - if(v->tuner!=0) - return -EINVAL; - /* Only 1 tuner so no setting needed ! */ - return 0; - } - case VIDIOCGFREQ: - { - unsigned long *freq = arg; - *freq = pcm20->freq; - return 0; - } - case VIDIOCSFREQ: - { - unsigned long *freq = arg; - pcm20->freq = *freq; - i=pcm20_setfreq(pcm20, pcm20->freq); - pr_debug("First view (setfreq): 0x%x\n", i); - return i; - } - case VIDIOCGAUDIO: - { - struct video_audio *v = arg; - memset(v,0, sizeof(*v)); - v->flags=VIDEO_AUDIO_MUTABLE; - if (pcm20->muted) - v->flags|=VIDEO_AUDIO_MUTE; - v->mode=VIDEO_SOUND_STEREO; - if (pcm20->stereo) - v->mode|=VIDEO_SOUND_MONO; - /* v->step=2048; */ - strcpy(v->name, "Radio"); - return 0; - } - case VIDIOCSAUDIO: - { - struct video_audio *v = arg; - if(v->audio) - return -EINVAL; - - pcm20_mute(pcm20, !!(v->flags&VIDEO_AUDIO_MUTE)); - if(v->flags&VIDEO_SOUND_MONO) - pcm20_stereo(pcm20, 0); - if(v->flags&VIDEO_SOUND_STEREO) - pcm20_stereo(pcm20, 1); - - return 0; - } - default: - return -ENOIOCTLCMD; - } -} - -static int pcm20_ioctl(struct inode *inode, struct file *file, - unsigned int cmd, unsigned long arg) -{ - return video_usercopy(inode, file, cmd, arg, pcm20_do_ioctl); -} - -static struct pcm20_device pcm20_unit = { - .freq = 87*16000, - .muted = 1, -}; - -static const struct file_operations pcm20_fops = { - .owner = THIS_MODULE, - .open = video_exclusive_open, - .release = video_exclusive_release, - .ioctl = pcm20_ioctl, -#ifdef CONFIG_COMPAT - .compat_ioctl = v4l_compat_ioctl32, -#endif - .llseek = no_llseek, -}; - -static struct video_device pcm20_radio = { - .name = "Miro PCM 20 radio", - .fops = &pcm20_fops, - .priv = &pcm20_unit -}; - -static int __init pcm20_init(void) -{ - if(video_register_device(&pcm20_radio, VFL_TYPE_RADIO, radio_nr)==-1) - goto video_register_device; - - if(attach_aci_rds()<0) - goto attach_aci_rds; - - printk(KERN_INFO "Miro PCM20 radio card driver.\n"); - - return 0; - - attach_aci_rds: - video_unregister_device(&pcm20_radio); - video_register_device: - return -EINVAL; -} - -MODULE_AUTHOR("Ruurd Reitsma"); -MODULE_DESCRIPTION("A driver for the Miro PCM20 radio card."); -MODULE_LICENSE("GPL"); - -static void __exit pcm20_cleanup(void) -{ - unload_aci_rds(); - video_unregister_device(&pcm20_radio); -} - -module_init(pcm20_init); -module_exit(pcm20_cleanup); diff --git a/drivers/media/radio/miropcm20-rds-core.c b/drivers/media/radio/miropcm20-rds-core.c deleted file mode 100644 index 9428d8b..0000000 --- a/drivers/media/radio/miropcm20-rds-core.c +++ /dev/null @@ -1,211 +0,0 @@ -/* - * Many thanks to Fred Seidel , the - * designer of the RDS decoder hardware. With his help - * I was able to code this driver. - * Thanks also to Norberto Pellicci, Dominic Mounteney - * and www.teleauskunft.de - * for good hints on finding Fred. It was somewhat hard - * to locate him here in Germany... [: - * - * Revision history: - * - * 2000-08-09 Robert Siemer - * RDS support for MiroSound PCM20 radio - */ - -#include -#include -#include -#include -#include -#include - -#include -#include "oss/aci.h" -#include "miropcm20-rds-core.h" - -#define DEBUG 0 - -static struct mutex aci_rds_mutex; - -#define RDS_DATASHIFT 2 /* Bit 2 */ -#define RDS_DATAMASK (1 << RDS_DATASHIFT) -#define RDS_BUSYMASK 0x10 /* Bit 4 */ -#define RDS_CLOCKMASK 0x08 /* Bit 3 */ - -#define RDS_DATA(x) (((x) >> RDS_DATASHIFT) & 1) - - -#if DEBUG -static void print_matrix(char array[], unsigned int length) -{ - int i, j; - - for (i=0; i=0; j--) { - printk("%d", (array[i] >> j) & 0x1); - } - if (i%8 == 0) - printk(" byte-border\n"); - else - printk("\n"); - } -} -#endif /* DEBUG */ - -static int byte2trans(unsigned char byte, unsigned char sendbuffer[], int size) -{ - int i; - - if (size != 8) - return -1; - for (i = 7; i >= 0; i--) - sendbuffer[7-i] = (byte & (1 << i)) ? RDS_DATAMASK : 0; - sendbuffer[0] |= RDS_CLOCKMASK; - - return 0; -} - -static int rds_waitread(void) -{ - unsigned char byte; - int i=2000; - - do { - byte=inb(RDS_REGISTER); - i--; - } - while ((byte & RDS_BUSYMASK) && i); - - if (i) { - #if DEBUG - printk(KERN_DEBUG "rds_waitread()"); - print_matrix(&byte, 1); - #endif - return (byte); - } else { - printk(KERN_WARNING "aci-rds: rds_waitread() timeout...\n"); - return -1; - } -} - -/* don't use any ..._nowait() function if you are not sure what you do... */ - -static inline void rds_rawwrite_nowait(unsigned char byte) -{ - #if DEBUG - printk(KERN_DEBUG "rds_rawwrite()"); - print_matrix(&byte, 1); - #endif - outb(byte, RDS_REGISTER); -} - -static int rds_rawwrite(unsigned char byte) -{ - if (rds_waitread() >= 0) { - rds_rawwrite_nowait(byte); - return 0; - } else - return -1; -} - -static int rds_write(unsigned char cmd) -{ - unsigned char sendbuffer[8]; - int i; - - if (byte2trans(cmd, sendbuffer, 8) != 0){ - return -1; - } else { - for (i=0; i<8; i++) { - rds_rawwrite(sendbuffer[i]); - } - } - return 0; -} - -static int rds_readcycle_nowait(void) -{ - rds_rawwrite_nowait(0); - return rds_waitread(); -} - -static int rds_readcycle(void) -{ - if (rds_rawwrite(0) < 0) - return -1; - return rds_waitread(); -} - -static int rds_read(unsigned char databuffer[], int datasize) -{ - #define READSIZE (8*datasize) - - int i,j; - - if (datasize < 1) /* nothing to read */ - return 0; - - /* to be able to use rds_readcycle_nowait() - I have to waitread() here */ - if (rds_waitread() < 0) - return -1; - - memset(databuffer, 0, datasize); - - for (i=0; i< READSIZE; i++) - if((j=rds_readcycle_nowait()) < 0) { - return -1; - } else { - databuffer[i/8]|=(RDS_DATA(j) << (7-(i%8))); - } - - return 0; -} - -static int rds_ack(void) -{ - int i=rds_readcycle(); - - if (i < 0) - return -1; - if (i & RDS_DATAMASK) { - return 0; /* ACK */ - } else { - printk(KERN_DEBUG "aci-rds: NACK\n"); - return 1; /* NACK */ - } -} - -int aci_rds_cmd(unsigned char cmd, unsigned char databuffer[], int datasize) -{ - int ret; - - if (mutex_lock_interruptible(&aci_rds_mutex)) - return -EINTR; - - rds_write(cmd); - - /* RDS_RESET doesn't need further processing */ - if (cmd!=RDS_RESET && (rds_ack() || rds_read(databuffer, datasize))) - ret = -1; - else - ret = 0; - - mutex_unlock(&aci_rds_mutex); - - return ret; -} -EXPORT_SYMBOL(aci_rds_cmd); - -int __init attach_aci_rds(void) -{ - mutex_init(&aci_rds_mutex); - return 0; -} - -void __exit unload_aci_rds(void) -{ -} -MODULE_LICENSE("GPL"); diff --git a/drivers/media/radio/miropcm20-rds-core.h b/drivers/media/radio/miropcm20-rds-core.h deleted file mode 100644 index aeb5761..0000000 --- a/drivers/media/radio/miropcm20-rds-core.h +++ /dev/null @@ -1,19 +0,0 @@ -#ifndef _MIROPCM20_RDS_CORE_H_ -#define _MIROPCM20_RDS_CORE_H_ - -extern int aci_rds_cmd(unsigned char cmd, unsigned char databuffer[], int datasize); - -#define RDS_STATUS 0x01 -#define RDS_STATIONNAME 0x02 -#define RDS_TEXT 0x03 -#define RDS_ALTFREQ 0x04 -#define RDS_TIMEDATE 0x05 -#define RDS_PI_CODE 0x06 -#define RDS_PTYTATP 0x07 -#define RDS_RESET 0x08 -#define RDS_RXVALUE 0x09 - -extern void __exit unload_aci_rds(void); -extern int __init attach_aci_rds(void); - -#endif /* _MIROPCM20_RDS_CORE_H_ */ diff --git a/drivers/media/radio/miropcm20-rds.c b/drivers/media/radio/miropcm20-rds.c deleted file mode 100644 index 3e840f7..0000000 --- a/drivers/media/radio/miropcm20-rds.c +++ /dev/null @@ -1,136 +0,0 @@ -/* MiroSOUND PCM20 radio rds interface driver - * (c) 2001 Robert Siemer - * Thanks to Fred Seidel. See miropcm20-rds-core.c for further information. - */ - -/* Revision history: - * - * 2001-04-18 Robert Siemer - * separate file for user interface driver - */ - -#include -#include -#include -#include -#include -#include -#include -#include -#include "miropcm20-rds-core.h" - -static char * text_buffer; -static int rds_users; - - -static int rds_f_open(struct inode *in, struct file *fi) -{ - if (rds_users) - return -EBUSY; - - lock_kernel(); - rds_users++; - if ((text_buffer=kmalloc(66, GFP_KERNEL)) == 0) { - rds_users--; - printk(KERN_NOTICE "aci-rds: Out of memory by open()...\n"); - unlock_kernel(); - return -ENOMEM; - } - - unlock_kernel(); - return 0; -} - -static int rds_f_release(struct inode *in, struct file *fi) -{ - kfree(text_buffer); - - rds_users--; - return 0; -} - -static void print_matrix(char *ch, char out[]) -{ - int j; - - for (j=7; j>=0; j--) { - out[7-j] = ((*ch >> j) & 0x1) + '0'; - } -} - -static ssize_t rds_f_read(struct file *file, char __user *buffer, size_t length, loff_t *offset) -{ -// i = sprintf(text_buffer, "length: %d, offset: %d\n", length, *offset); - - char c; - char bits[8]; - - msleep(2000); - aci_rds_cmd(RDS_STATUS, &c, 1); - print_matrix(&c, bits); - if (copy_to_user(buffer, bits, 8)) - return -EFAULT; - -/* if ((c >> 3) & 1) { - aci_rds_cmd(RDS_STATIONNAME, text_buffer+1, 8); - text_buffer[0] = ' ' ; - text_buffer[9] = '\n'; - return copy_to_user(buffer+8, text_buffer, 10) ? -EFAULT: 18; - } -*/ -/* if ((c >> 6) & 1) { - aci_rds_cmd(RDS_PTYTATP, &c, 1); - if ( c & 1) - sprintf(text_buffer, " M"); - else - sprintf(text_buffer, " S"); - if ((c >> 1) & 1) - sprintf(text_buffer+2, " TA"); - else - sprintf(text_buffer+2, " --"); - if ((c >> 7) & 1) - sprintf(text_buffer+5, " TP"); - else - sprintf(text_buffer+5, " --"); - sprintf(text_buffer+8, " %2d\n", (c >> 2) & 0x1f); - return copy_to_user(buffer+8, text_buffer, 12) ? -EFAULT: 20; - } -*/ - - if ((c >> 4) & 1) { - aci_rds_cmd(RDS_TEXT, text_buffer, 65); - text_buffer[0] = ' ' ; - text_buffer[65] = '\n'; - return copy_to_user(buffer+8, text_buffer,66) ? -EFAULT : 66+8; - } else { - put_user('\n', buffer+8); - return 9; - } -} - -static const struct file_operations rds_fops = { - .owner = THIS_MODULE, - .read = rds_f_read, - .open = rds_f_open, - .release = rds_f_release -}; - -static struct miscdevice rds_miscdev = { - .minor = MISC_DYNAMIC_MINOR, - .name = "radiotext", - .fops = &rds_fops, -}; - -static int __init miropcm20_rds_init(void) -{ - return misc_register(&rds_miscdev); -} - -static void __exit miropcm20_rds_cleanup(void) -{ - misc_deregister(&rds_miscdev); -} - -module_init(miropcm20_rds_init); -module_exit(miropcm20_rds_cleanup); -MODULE_LICENSE("GPL"); -- cgit v0.10.2 From b045979d61b235cd9cc8347760fcfb44fc8ecbd6 Mon Sep 17 00:00:00 2001 From: Alexander Beregalov Date: Wed, 3 Sep 2008 16:47:38 -0300 Subject: V4L/DVB (8681): v4l2-ioctl.c: fix warning drivers/media/video/v4l2-ioctl.c:496: warning: format '%08ld' expects type 'long int', but argument 5 has type 'suseconds_t' Signed-off-by: Alexander Beregalov Signed-off-by: Mauro Carvalho Chehab diff --git a/drivers/media/video/v4l2-ioctl.c b/drivers/media/video/v4l2-ioctl.c index 88c0465..140ef92 100644 --- a/drivers/media/video/v4l2-ioctl.c +++ b/drivers/media/video/v4l2-ioctl.c @@ -499,7 +499,7 @@ static void dbgbuf(unsigned int cmd, struct video_device *vfd, p->timestamp.tv_sec / 3600, (int)(p->timestamp.tv_sec / 60) % 60, (int)(p->timestamp.tv_sec % 60), - p->timestamp.tv_usec, + (long)p->timestamp.tv_usec, p->index, prt_names(p->type, v4l2_type_names), p->bytesused, p->flags, -- cgit v0.10.2 From 46f2c21cfdb1a829a9a23e23562ffa66b007dc48 Mon Sep 17 00:00:00 2001 From: Henrik Kretzschmar Date: Wed, 3 Sep 2008 16:47:39 -0300 Subject: V4L/DVB (8682): V4L: fix return value of register video func If a wrong device type is used with video_register_device_index() it should better return an error number, instead of a constant. Signed-off-by: Henrik Kretzschmar Signed-off-by: Mauro Carvalho Chehab diff --git a/drivers/media/video/v4l2-dev.c b/drivers/media/video/v4l2-dev.c index 6f36006..0320fb8 100644 --- a/drivers/media/video/v4l2-dev.c +++ b/drivers/media/video/v4l2-dev.c @@ -281,7 +281,7 @@ int video_register_device_index(struct video_device *vfd, int type, int nr, default: printk(KERN_ERR "%s called with unknown type: %d\n", __func__, type); - return -1; + return -EINVAL; } /* pick a minor number */ -- cgit v0.10.2 From 0058717a1ef0c87deeccbe0a3b17def173fee9a9 Mon Sep 17 00:00:00 2001 From: Andy Walls Date: Wed, 3 Sep 2008 16:47:50 -0300 Subject: V4L/DVB (8701): cx18: Add missing lock for when the irq handler manipulates the queues cx18: Add missing lock for when the irq handler manipulates the queues. This was a potential source of stream queue corruption. Also changed the name of cx18_queue_find_buf() to cx18_queue_get_buf_irq(). Signed-off-by: Andy Walls Signed-off-by: Mauro Carvalho Chehab diff --git a/drivers/media/video/cx18/cx18-irq.c b/drivers/media/video/cx18/cx18-irq.c index 25114a5..ab21831 100644 --- a/drivers/media/video/cx18/cx18-irq.c +++ b/drivers/media/video/cx18/cx18-irq.c @@ -61,7 +61,7 @@ static void epu_dma_done(struct cx18 *cx, struct cx18_mailbox *mb) CX18_WARN("Ack struct = %d for %s\n", mb->args[2], s->name); id = read_enc(off); - buf = cx18_queue_find_buf(s, id, read_enc(off + 4)); + buf = cx18_queue_get_buf_irq(s, id, read_enc(off + 4)); CX18_DEBUG_HI_DMA("DMA DONE for %s (buffer %d)\n", s->name, id); if (buf) { cx18_buf_sync_for_cpu(s, buf); diff --git a/drivers/media/video/cx18/cx18-queue.c b/drivers/media/video/cx18/cx18-queue.c index 6990b77..8a4dd82 100644 --- a/drivers/media/video/cx18/cx18-queue.c +++ b/drivers/media/video/cx18/cx18-queue.c @@ -78,12 +78,13 @@ struct cx18_buffer *cx18_dequeue(struct cx18_stream *s, struct cx18_queue *q) return buf; } -struct cx18_buffer *cx18_queue_find_buf(struct cx18_stream *s, u32 id, +struct cx18_buffer *cx18_queue_get_buf_irq(struct cx18_stream *s, u32 id, u32 bytesused) { struct cx18 *cx = s->cx; struct list_head *p; + spin_lock(&s->qlock); list_for_each(p, &s->q_free.list) { struct cx18_buffer *buf = list_entry(p, struct cx18_buffer, list); @@ -92,17 +93,19 @@ struct cx18_buffer *cx18_queue_find_buf(struct cx18_stream *s, u32 id, continue; buf->bytesused = bytesused; /* the transport buffers are handled differently, - so there is no need to move them to the full queue */ - if (s->type == CX18_ENC_STREAM_TYPE_TS) - return buf; - s->q_free.buffers--; - s->q_free.length -= s->buf_size; - s->q_full.buffers++; - s->q_full.length += s->buf_size; - s->q_full.bytesused += buf->bytesused; - list_move_tail(&buf->list, &s->q_full.list); + they are not moved to the full queue */ + if (s->type != CX18_ENC_STREAM_TYPE_TS) { + s->q_free.buffers--; + s->q_free.length -= s->buf_size; + s->q_full.buffers++; + s->q_full.length += s->buf_size; + s->q_full.bytesused += buf->bytesused; + list_move_tail(&buf->list, &s->q_full.list); + } + spin_unlock(&s->qlock); return buf; } + spin_unlock(&s->qlock); CX18_ERR("Cannot find buffer %d for stream %s\n", id, s->name); return NULL; } diff --git a/drivers/media/video/cx18/cx18-queue.h b/drivers/media/video/cx18/cx18-queue.h index 91423b9..7f93bb1 100644 --- a/drivers/media/video/cx18/cx18-queue.h +++ b/drivers/media/video/cx18/cx18-queue.h @@ -46,7 +46,7 @@ void cx18_queue_init(struct cx18_queue *q); void cx18_enqueue(struct cx18_stream *s, struct cx18_buffer *buf, struct cx18_queue *q); struct cx18_buffer *cx18_dequeue(struct cx18_stream *s, struct cx18_queue *q); -struct cx18_buffer *cx18_queue_find_buf(struct cx18_stream *s, u32 id, +struct cx18_buffer *cx18_queue_get_buf_irq(struct cx18_stream *s, u32 id, u32 bytesused); void cx18_flush_queues(struct cx18_stream *s); -- cgit v0.10.2 From d698dc6b0477d3165a7f320b3ce36d1cbd361c94 Mon Sep 17 00:00:00 2001 From: Jean-Francois Moine Date: Wed, 3 Sep 2008 16:47:51 -0300 Subject: V4L/DVB (8703): gspca: Do controls work for spca561 revision 12a. Signed-off-by: Jean-Francois Moine Signed-off-by: Mauro Carvalho Chehab diff --git a/drivers/media/video/gspca/spca561.c b/drivers/media/video/gspca/spca561.c index 0a2b8bc..0a1e662 100644 --- a/drivers/media/video/gspca/spca561.c +++ b/drivers/media/video/gspca/spca561.c @@ -38,9 +38,9 @@ struct sd { #define CONTRAST_MAX 0x3fff __u16 exposure; /* rev12a only */ -#define EXPOSURE_MIN 0x0120 +#define EXPOSURE_MIN 0x2001 #define EXPOSURE_DEF 0x20ae -#define EXPOSURE_MAX 0x5720 +#define EXPOSURE_MAX 0x421d __u8 brightness; /* rev72a only */ #define BRIGHTNESS_MIN 0 @@ -62,6 +62,9 @@ struct sd { #define GAIN_DEF 0x24 #define GAIN_MAX 0x24 +#define EXPO12A_DEF 3 + __u8 expo12a; /* expo/gain? for rev 12a */ + __u8 chip_revision; #define Rev012A 0 #define Rev072A 1 @@ -553,6 +556,7 @@ static int sd_config(struct gspca_dev *gspca_dev, sd->exposure = EXPOSURE_DEF; sd->autogain = AUTOGAIN_DEF; sd->gain = GAIN_DEF; + sd->expo12a = EXPO12A_DEF; return 0; } @@ -609,12 +613,9 @@ static void setwhite(struct gspca_dev *gspca_dev) return; } /* try to emulate MS-win as possible */ - if (white < 0x45) - reg8616 = white; - else - reg8616 = 0x93 + (white >> 2); - reg8614 = 0x28 + (white >> 4); + reg8616 = 0x90 - white * 5 / 8; reg_w_val(gspca_dev->dev, 0x8616, reg8616); + reg8614 = 0x20 + white * 3 / 8; reg_w_val(gspca_dev->dev, 0x8614, reg8614); } @@ -622,30 +623,32 @@ static void setwhite(struct gspca_dev *gspca_dev) static void setexposure(struct gspca_dev *gspca_dev) { struct sd *sd = (struct sd *) gspca_dev; - struct usb_device *dev = gspca_dev->dev; + __u8 data[2]; - reg_w_val(dev, 0x8309, sd->gain); + data[0] = sd->exposure; + data[1] = sd->exposure >> 8; + reg_w_buf(gspca_dev, 0x8309, data, 2); } /* rev 12a only */ static void setgain(struct gspca_dev *gspca_dev) { struct sd *sd = (struct sd *) gspca_dev; - struct usb_device *dev = gspca_dev->dev; + __u8 data[2]; - reg_w_val(dev, 0x8335, sd->gain); + data[0] = sd->gain; + data[1] = 0; + reg_w_buf(gspca_dev, 0x8335, data, 2); } static void setautogain(struct gspca_dev *gspca_dev) { struct sd *sd = (struct sd *) gspca_dev; - if (sd->chip_revision == Rev072A) { - if (sd->autogain) - sd->ag_cnt = AG_CNT_START; - else - sd->ag_cnt = -1; - } + if (sd->autogain) + sd->ag_cnt = AG_CNT_START; + else + sd->ag_cnt = -1; } static void sd_start_12a(struct gspca_dev *gspca_dev) @@ -684,6 +687,7 @@ static void sd_start_12a(struct gspca_dev *gspca_dev) reg_w_val(gspca_dev->dev, 0x850b, 0x03); setcontrast(gspca_dev); setwhite(gspca_dev); + setautogain(gspca_dev); } static void sd_start_72a(struct gspca_dev *gspca_dev) { @@ -713,12 +717,24 @@ static void sd_start_72a(struct gspca_dev *gspca_dev) static void sd_stopN(struct gspca_dev *gspca_dev) { - reg_w_val(gspca_dev->dev, 0x8112, 0x20); - reg_w_val(gspca_dev->dev, 0x8102, 0x00); /* white balance - new */ + struct sd *sd = (struct sd *) gspca_dev; + + if (sd->chip_revision == Rev012A) { + reg_w_val(gspca_dev->dev, 0x8112, 0x0e); + } else { + reg_w_val(gspca_dev->dev, 0x8112, 0x20); +/* reg_w_val(gspca_dev->dev, 0x8102, 0x00); ?? */ + } } static void sd_stop0(struct gspca_dev *gspca_dev) { + struct sd *sd = (struct sd *) gspca_dev; + + if (sd->chip_revision == Rev012A) { + reg_w_val(gspca_dev->dev, 0x8118, 0x29); + reg_w_val(gspca_dev->dev, 0x8114, 0x08); + } } /* this function is called at close time */ @@ -727,7 +743,6 @@ static void sd_close(struct gspca_dev *gspca_dev) reg_w_val(gspca_dev->dev, 0x8114, 0); } -/* rev72a only */ static void do_autogain(struct gspca_dev *gspca_dev) { struct sd *sd = (struct sd *) gspca_dev; @@ -739,6 +754,7 @@ static void do_autogain(struct gspca_dev *gspca_dev) __u8 luma_mean = 110; __u8 luma_delta = 20; __u8 spring = 4; + __u8 reg8339[2]; if (sd->ag_cnt < 0) return; @@ -793,13 +809,16 @@ static void do_autogain(struct gspca_dev *gspca_dev) } break; case Rev012A: - /* sensor registers is access and memory mapped to 0x8300 */ - /* readind all 0x83xx block the sensor */ - /* - * The data from the header seem wrong where is the luma - * and chroma mean value - * at the moment set exposure in contrast set - */ + reg_r(gspca_dev, 0x8330, 2); + if (gspca_dev->usb_buf[1] > 0x08) { + reg8339[0] = ++sd->expo12a; + reg8339[1] = 0; + reg_w_buf(gspca_dev, 0x8339, reg8339, 2); + } else if (gspca_dev->usb_buf[1] < 0x02) { + reg8339[0] = --sd->expo12a; + reg8339[1] = 0; + reg_w_buf(gspca_dev, 0x8339, reg8339, 2); + } break; } } -- cgit v0.10.2 From 3a1ea7050345734acc3a33b2b00a611b9b7bf640 Mon Sep 17 00:00:00 2001 From: Jean-Francois Moine Date: Wed, 3 Sep 2008 16:47:55 -0300 Subject: V4L/DVB (8705): gspca: Adjust some control limits in spca561. Signed-off-by: Jean-Francois Moine Signed-off-by: Mauro Carvalho Chehab diff --git a/drivers/media/video/gspca/spca561.c b/drivers/media/video/gspca/spca561.c index 0a1e662..ec575f5 100644 --- a/drivers/media/video/gspca/spca561.c +++ b/drivers/media/video/gspca/spca561.c @@ -38,9 +38,9 @@ struct sd { #define CONTRAST_MAX 0x3fff __u16 exposure; /* rev12a only */ -#define EXPOSURE_MIN 0x2001 -#define EXPOSURE_DEF 0x20ae -#define EXPOSURE_MAX 0x421d +#define EXPOSURE_MIN 0 +#define EXPOSURE_DEF 200 +#define EXPOSURE_MAX 762 __u8 brightness; /* rev72a only */ #define BRIGHTNESS_MIN 0 @@ -48,7 +48,7 @@ struct sd { #define BRIGHTNESS_MAX 63 __u8 white; /* rev12a only */ -#define WHITE_MIN 0 +#define WHITE_MIN 1 #define WHITE_DEF 0x40 #define WHITE_MAX 0x7f @@ -608,10 +608,6 @@ static void setwhite(struct gspca_dev *gspca_dev) __u8 reg8614, reg8616; white = sd->white; - if (sd->white == 0) { - PDEBUG(D_CONF, "Discarding null whiteness"); - return; - } /* try to emulate MS-win as possible */ reg8616 = 0x90 - white * 5 / 8; reg_w_val(gspca_dev->dev, 0x8616, reg8616); @@ -623,10 +619,12 @@ static void setwhite(struct gspca_dev *gspca_dev) static void setexposure(struct gspca_dev *gspca_dev) { struct sd *sd = (struct sd *) gspca_dev; + int expo; __u8 data[2]; - data[0] = sd->exposure; - data[1] = sd->exposure >> 8; + expo = sd->exposure + 0x20a8; /* from test */ + data[0] = expo; + data[1] = expo >> 8; reg_w_buf(gspca_dev, 0x8309, data, 2); } -- cgit v0.10.2 From dff6d321d421c4c059aea72be70df3a8a200b8a3 Mon Sep 17 00:00:00 2001 From: Jean-Francois Moine Date: Wed, 3 Sep 2008 16:47:57 -0300 Subject: V4L/DVB (8706): Make contrast and brightness work for pac7302. Signed-off-by: Jean-Francois Moine Signed-off-by: Mauro Carvalho Chehab diff --git a/drivers/media/video/gspca/pac7311.c b/drivers/media/video/gspca/pac7311.c index 3c9f2b1..3abc018 100644 --- a/drivers/media/video/gspca/pac7311.c +++ b/drivers/media/video/gspca/pac7311.c @@ -82,9 +82,10 @@ static struct ctrl sd_ctrls[] = { .type = V4L2_CTRL_TYPE_INTEGER, .name = "Contrast", .minimum = 0, - .maximum = 255, +#define CONTRAST_MAX 255 + .maximum = CONTRAST_MAX, .step = 1, -#define CONTRAST_DEF 127 +#define CONTRAST_DEF 60 .default_value = CONTRAST_DEF, }, .set = sd_setcontrast, @@ -94,7 +95,7 @@ static struct ctrl sd_ctrls[] = { { .id = V4L2_CID_SATURATION, .type = V4L2_CTRL_TYPE_INTEGER, - .name = "Color", + .name = "Saturation", .minimum = 0, .maximum = 255, .step = 1, @@ -429,13 +430,42 @@ static int sd_config(struct gspca_dev *gspca_dev, return 0; } +/* rev 12a only */ +static void setbrightcont(struct gspca_dev *gspca_dev) +{ + struct sd *sd = (struct sd *) gspca_dev; + int i, v; + static const __u8 max[10] = + {0x29, 0x33, 0x42, 0x5a, 0x6e, 0x80, 0x9f, 0xbb, + 0xd4, 0xec}; + static const __u8 delta[10] = + {0x35, 0x33, 0x33, 0x2f, 0x2a, 0x25, 0x1e, 0x17, + 0x11, 0x0b}; + + reg_w(gspca_dev, 0xff, 0x00); /* page 0 */ + for (i = 0; i < 10; i++) { + v = max[i]; + v += (sd->brightness - BRIGHTNESS_MAX) + * 150 / BRIGHTNESS_MAX; /* 200 ? */ + v -= delta[i] * sd->contrast / CONTRAST_MAX; + if (v < 0) + v = 0; + else if (v > 0xff) + v = 0xff; + reg_w(gspca_dev, 0xa2 + i, v); + } + reg_w(gspca_dev, 0xdc, 0x01); +} + static void setbrightness(struct gspca_dev *gspca_dev) { struct sd *sd = (struct sd *) gspca_dev; int brightness; - if (sd->sensor == SENSOR_PAC7302) + if (sd->sensor == SENSOR_PAC7302) { + setbrightcont(gspca_dev); return; + } /*jfm: inverted?*/ brightness = BRIGHTNESS_MAX - sd->brightness; reg_w(gspca_dev, 0xff, 0x04); @@ -449,13 +479,14 @@ static void setcontrast(struct gspca_dev *gspca_dev) { struct sd *sd = (struct sd *) gspca_dev; - if (sd->sensor == SENSOR_PAC7302) + if (sd->sensor == SENSOR_PAC7302) { + setbrightcont(gspca_dev); return; + } reg_w(gspca_dev, 0xff, 0x01); reg_w(gspca_dev, 0x80, sd->contrast); /* load registers to sensor (Bit 0, auto clear) */ reg_w(gspca_dev, 0x11, 0x01); - PDEBUG(D_CONF|D_STREAM, "contrast: %i", sd->contrast); } static void setcolors(struct gspca_dev *gspca_dev) -- cgit v0.10.2 From 41b469745f6218efb22bec4e3940b085ffb97216 Mon Sep 17 00:00:00 2001 From: Jean-Francois Moine Date: Wed, 3 Sep 2008 16:47:58 -0300 Subject: V4L/DVB (8707): gspca: Colors, hflip and vflip controls added for pac7302. Signed-off-by: Jean-Francois Moine Signed-off-by: Mauro Carvalho Chehab diff --git a/drivers/media/video/gspca/pac7311.c b/drivers/media/video/gspca/pac7311.c index 3abc018..a89cc9f 100644 --- a/drivers/media/video/gspca/pac7311.c +++ b/drivers/media/video/gspca/pac7311.c @@ -40,6 +40,8 @@ struct sd { unsigned char contrast; unsigned char colors; unsigned char autogain; + __u8 hflip; + __u8 vflip; char tosof; /* number of bytes before next start of frame */ signed char ag_cnt; @@ -59,6 +61,10 @@ static int sd_setcolors(struct gspca_dev *gspca_dev, __s32 val); static int sd_getcolors(struct gspca_dev *gspca_dev, __s32 *val); static int sd_setautogain(struct gspca_dev *gspca_dev, __s32 val); static int sd_getautogain(struct gspca_dev *gspca_dev, __s32 *val); +static int sd_sethflip(struct gspca_dev *gspca_dev, __s32 val); +static int sd_gethflip(struct gspca_dev *gspca_dev, __s32 *val); +static int sd_setvflip(struct gspca_dev *gspca_dev, __s32 val); +static int sd_getvflip(struct gspca_dev *gspca_dev, __s32 *val); static struct ctrl sd_ctrls[] = { { @@ -97,7 +103,8 @@ static struct ctrl sd_ctrls[] = { .type = V4L2_CTRL_TYPE_INTEGER, .name = "Saturation", .minimum = 0, - .maximum = 255, +#define COLOR_MAX 255 + .maximum = COLOR_MAX, .step = 1, #define COLOR_DEF 127 .default_value = COLOR_DEF, @@ -119,6 +126,35 @@ static struct ctrl sd_ctrls[] = { .set = sd_setautogain, .get = sd_getautogain, }, +/* next controls work with pac7302 only */ + { + { + .id = V4L2_CID_HFLIP, + .type = V4L2_CTRL_TYPE_BOOLEAN, + .name = "Mirror", + .minimum = 0, + .maximum = 1, + .step = 1, +#define HFLIP_DEF 0 + .default_value = HFLIP_DEF, + }, + .set = sd_sethflip, + .get = sd_gethflip, + }, + { + { + .id = V4L2_CID_VFLIP, + .type = V4L2_CTRL_TYPE_BOOLEAN, + .name = "Vflip", + .minimum = 0, + .maximum = 1, + .step = 1, +#define VFLIP_DEF 0 + .default_value = VFLIP_DEF, + }, + .set = sd_setvflip, + .get = sd_getvflip, + }, }; static struct v4l2_pix_format vga_mode[] = { @@ -493,8 +529,25 @@ static void setcolors(struct gspca_dev *gspca_dev) { struct sd *sd = (struct sd *) gspca_dev; - if (sd->sensor == SENSOR_PAC7302) + if (sd->sensor == SENSOR_PAC7302) { + int i, v; + static const int a[9] = + {217, -212, 0, -101, 170, -67, -38, -315, 355}; + static const int b[9] = + {19, 106, 0, 19, 106, 1, 19, 106, 1}; + + reg_w(gspca_dev, 0xff, 0x03); /* page 3 */ + reg_w(gspca_dev, 0x11, 0x01); + reg_w(gspca_dev, 0xff, 0x00); /* page 0 */ + reg_w(gspca_dev, 0xff, 0x00); /* page 0 */ + for (i = 0; i < 9; i++) { + v = a[i] * sd->colors / COLOR_MAX + b[i]; + reg_w(gspca_dev, 0x0f + 2 * i, (v >> 8) & 0x07); + reg_w(gspca_dev, 0x0f + 2 * i + 1, v); + } + reg_w(gspca_dev, 0xdc, 0x01); return; + } reg_w(gspca_dev, 0xff, 0x01); reg_w(gspca_dev, 0x10, sd->colors); /* load registers to sensor (Bit 0, auto clear) */ @@ -514,6 +567,19 @@ static void setautogain(struct gspca_dev *gspca_dev) } } +/* this function is used by pac7302 only */ +static void sethvflip(struct gspca_dev *gspca_dev) +{ + struct sd *sd = (struct sd *) gspca_dev; + __u8 data; + + reg_w(gspca_dev, 0xff, 0x03); /* page 3 */ + data = (sd->hflip ? 0x00 : 0x08) + | (sd->vflip ? 0x04 : 0x00); + reg_w(gspca_dev, 0x21, data); + reg_w(gspca_dev, 0x11, 0x01); +} + /* this function is called at open time */ static int sd_open(struct gspca_dev *gspca_dev) { @@ -574,6 +640,7 @@ static void sd_start(struct gspca_dev *gspca_dev) /* start stream */ reg_w(gspca_dev, 0xff, 0x01); if (sd->sensor == SENSOR_PAC7302) { + sethvflip(gspca_dev); reg_w(gspca_dev, 0x78, 0x01); reg_w(gspca_dev, 0xff, 0x01); reg_w(gspca_dev, 0x78, 0x01); @@ -790,6 +857,42 @@ static int sd_getautogain(struct gspca_dev *gspca_dev, __s32 *val) return 0; } +static int sd_sethflip(struct gspca_dev *gspca_dev, __s32 val) +{ + struct sd *sd = (struct sd *) gspca_dev; + + sd->hflip = val; + if (gspca_dev->streaming) + sethvflip(gspca_dev); + return 0; +} + +static int sd_gethflip(struct gspca_dev *gspca_dev, __s32 *val) +{ + struct sd *sd = (struct sd *) gspca_dev; + + *val = sd->hflip; + return 0; +} + +static int sd_setvflip(struct gspca_dev *gspca_dev, __s32 val) +{ + struct sd *sd = (struct sd *) gspca_dev; + + sd->vflip = val; + if (gspca_dev->streaming) + sethvflip(gspca_dev); + return 0; +} + +static int sd_getvflip(struct gspca_dev *gspca_dev, __s32 *val) +{ + struct sd *sd = (struct sd *) gspca_dev; + + *val = sd->vflip; + return 0; +} + /* sub-driver description */ static struct sd_desc sd_desc = { .name = MODULE_NAME, -- cgit v0.10.2 From 05b809c702bf297690c63ea78ee117c4dc909028 Mon Sep 17 00:00:00 2001 From: Jean-Francois Moine Date: Wed, 3 Sep 2008 16:47:59 -0300 Subject: V4L/DVB (8709): gspca: Fix initialization and controls of sn9x110 - ov7630. Signed-off-by: Jean-Francois Moine Signed-off-by: Mauro Carvalho Chehab diff --git a/drivers/media/video/gspca/sonixj.c b/drivers/media/video/gspca/sonixj.c index 47737bf..b17aaa4 100644 --- a/drivers/media/video/gspca/sonixj.c +++ b/drivers/media/video/gspca/sonixj.c @@ -59,6 +59,7 @@ struct sd { #define SENSOR_OV7648 5 #define SENSOR_OV7660 6 unsigned char i2c_base; + __u8 regf1; }; /* V4L2 controls supported by the driver */ @@ -78,7 +79,8 @@ static struct ctrl sd_ctrls[] = { .type = V4L2_CTRL_TYPE_INTEGER, .name = "Brightness", .minimum = 0, - .maximum = 0xffff, +#define BRIGHTNESS_MAX 0xffff + .maximum = BRIGHTNESS_MAX, .step = 1, #define BRIGHTNESS_DEF 0x7fff .default_value = BRIGHTNESS_DEF, @@ -92,7 +94,8 @@ static struct ctrl sd_ctrls[] = { .type = V4L2_CTRL_TYPE_INTEGER, .name = "Contrast", .minimum = 0, - .maximum = 127, +#define CONTRAST_MAX 127 + .maximum = CONTRAST_MAX, .step = 1, #define CONTRAST_DEF 63 .default_value = CONTRAST_DEF, @@ -240,27 +243,16 @@ static const __u8 *sn_tb[] = { sn_ov7660 }; -static const __u8 regsn20[] = { +static const __u8 gamma_def[] = { 0x00, 0x2d, 0x46, 0x5a, 0x6c, 0x7c, 0x8b, 0x99, 0xa6, 0xb2, 0xbf, 0xca, 0xd5, 0xe0, 0xeb, 0xf5, 0xff }; -static const __u8 regsn20_sn9c325[] = { - 0x0a, 0x3a, 0x56, 0x6c, 0x7e, 0x8d, 0x9a, 0xa4, - 0xaf, 0xbb, 0xc5, 0xcd, 0xd5, 0xde, 0xe8, 0xed, 0xf5 -}; static const __u8 reg84[] = { 0x14, 0x00, 0x27, 0x00, 0x07, 0x00, 0xe5, 0x0f, 0xe4, 0x0f, 0x38, 0x00, 0x3e, 0x00, 0xc3, 0x0f, -/* 0x00, 0x00, 0x00, 0x00, 0x00 */ - 0xf7, 0x0f, 0x0a, 0x00, 0x00 -}; -static const __u8 reg84_sn9c325[] = { - 0x14, 0x00, 0x27, 0x00, 0x07, 0x00, 0xe4, 0x0f, - 0xd3, 0x0f, 0x4b, 0x00, 0x48, 0x00, 0xc0, 0x0f, - 0xf8, 0x0f, 0x00, 0x00, 0x00 + 0xf7, 0x0f, 0x00, 0x00, 0x00 }; - static const __u8 hv7131r_sensor_init[][8] = { {0xC1, 0x11, 0x01, 0x08, 0x01, 0x00, 0x00, 0x10}, {0xB1, 0x11, 0x34, 0x17, 0x7F, 0x00, 0x00, 0x10}, @@ -411,7 +403,7 @@ static const __u8 ov7630_sensor_init[][8] = { {0xa1, 0x21, 0x12, 0xc8, 0x00, 0x00, 0x00, 0x10}, /* win: delay 20ms */ {0xa1, 0x21, 0x12, 0x48, 0x00, 0x00, 0x00, 0x10}, -/* win: loop on 2 wwrite, 1 read */ +/* win: i2c_r from 00 to 80 */ {0xd1, 0x21, 0x03, 0x80, 0x10, 0x20, 0x80, 0x10}, {0xb1, 0x21, 0x0c, 0x20, 0x20, 0x00, 0x00, 0x10}, {0xd1, 0x21, 0x11, 0x00, 0x48, 0xc0, 0x00, 0x10}, @@ -446,9 +438,11 @@ static const __u8 ov7630_sensor_init[][8] = { {0xa1, 0x21, 0x10, 0x32, 0x00, 0x00, 0x00, 0x10}, {0xa1, 0x21, 0x00, 0x00, 0x00, 0x00, 0x00, 0x10}, {0xb1, 0x21, 0x01, 0x80, 0x80, 0x00, 0x00, 0x10}, +/* */ {0xa1, 0x21, 0x11, 0x00, 0x00, 0x00, 0x00, 0x10}, {0xa1, 0x21, 0x2a, 0x88, 0x00, 0x00, 0x00, 0x10}, {0xa1, 0x21, 0x2b, 0x34, 0x00, 0x00, 0x00, 0x10}, +/* */ {0xa1, 0x21, 0x10, 0x83, 0x00, 0x00, 0x00, 0x10}, {0xb1, 0x21, 0x01, 0x88, 0x70, 0x00, 0x00, 0x10}, {} @@ -778,7 +772,7 @@ static int configure_gpio(struct gspca_dev *gspca_dev, static const __u8 regd4[] = {0x60, 0x00, 0x00}; reg_w1(gspca_dev, 0xf1, 0x00); - reg_w1(gspca_dev, 0x01, 0x00); /*jfm was sn9c1xx[1] in v1*/ + reg_w1(gspca_dev, 0x01, sn9c1xx[1]); /* configure gpio */ reg_w(gspca_dev, 0x01, &sn9c1xx[1], 2); @@ -805,6 +799,13 @@ static int configure_gpio(struct gspca_dev *gspca_dev, reg_w1(gspca_dev, 0x17, 0x64); reg_w1(gspca_dev, 0x01, 0x42); break; +/*jfm: from win trace */ + case SENSOR_OV7630: + reg_w1(gspca_dev, 0x01, 0x61); + reg_w1(gspca_dev, 0x17, 0xe2); + reg_w1(gspca_dev, 0x01, 0x60); + reg_w1(gspca_dev, 0x01, 0x40); + break; case SENSOR_OV7648: reg_w1(gspca_dev, 0x01, 0x43); reg_w1(gspca_dev, 0x17, 0xae); @@ -870,9 +871,20 @@ static void ov7630_InitSensor(struct gspca_dev *gspca_dev) { int i = 0; - i2c_w8(gspca_dev, ov7630_sensor_init[i]); + i2c_w8(gspca_dev, ov7630_sensor_init[i]); /* 76 01 */ + i++; + i2c_w8(gspca_dev, ov7630_sensor_init[i]); /* 12 c8 (RGB+SRST) */ i++; msleep(20); + i2c_w8(gspca_dev, ov7630_sensor_init[i]); /* 12 48 */ + i++; + i2c_w8(gspca_dev, ov7630_sensor_init[i]); /* 12 c8 */ + i++; + msleep(20); + i2c_w8(gspca_dev, ov7630_sensor_init[i]); /* 12 48 */ + i++; +/*jfm:win i2c_r from 00 to 80*/ + while (ov7630_sensor_init[i][0]) { i2c_w8(gspca_dev, ov7630_sensor_init[i]); i++; @@ -917,6 +929,7 @@ static int sd_config(struct gspca_dev *gspca_dev, sd->bridge = id->driver_info >> 16; sd->sensor = id->driver_info >> 8; sd->i2c_base = id->driver_info; + sd->regf1 = 0; /*jfm: was 1 in v1*/ sd->qindex = 4; /* set the quantization table */ sd->brightness = BRIGHTNESS_DEF; @@ -969,7 +982,7 @@ static int sd_open(struct gspca_dev *gspca_dev) break; } - reg_w1(gspca_dev, 0xf1, 0x01); + reg_w1(gspca_dev, 0xf1, sd->regf1); return 0; } @@ -1051,6 +1064,28 @@ static unsigned int setexposure(struct gspca_dev *gspca_dev, return expo; } +/* this function is used for sensors o76xx only */ +static void setbrightcont(struct gspca_dev *gspca_dev) +{ + struct sd *sd = (struct sd *) gspca_dev; + unsigned val; + __u8 reg84_full[13]; + + memset(reg84_full, 0, sizeof reg84_full); + val = sd->contrast * 0x20 / CONTRAST_MAX + 0x10; /* 10..30 */ + reg84_full[2] = val; + reg84_full[0] = (val + 1) / 2; + reg84_full[4] = (val + 1) / 5; + if (val > BRIGHTNESS_DEF) + val = (sd->brightness - BRIGHTNESS_DEF) * 0x20 + / BRIGHTNESS_MAX; + else + val = 0; + reg84_full[10] = val; /* 00..1f */ + reg_w(gspca_dev, 0x84, reg84_full, sizeof reg84_full); +} + +/* sensor != ov76xx */ static void setbrightness(struct gspca_dev *gspca_dev) { struct sd *sd = (struct sd *) gspca_dev; @@ -1082,6 +1117,7 @@ static void setbrightness(struct gspca_dev *gspca_dev) reg_w1(gspca_dev, 0x96, k2); } +/* sensor != ov76xx */ static void setcontrast(struct gspca_dev *gspca_dev) { struct sd *sd = (struct sd *) gspca_dev; @@ -1175,24 +1211,11 @@ static void sd_start(struct gspca_dev *gspca_dev) reg_w1(gspca_dev, 0x07, sn9c1xx[7]); reg_w1(gspca_dev, 0x06, sn9c1xx[6]); reg_w1(gspca_dev, 0x14, sn9c1xx[0x14]); - switch (sd->bridge) { - case BRIDGE_SN9C325: - reg_w(gspca_dev, 0x20, regsn20_sn9c325, - sizeof regsn20_sn9c325); - for (i = 0; i < 8; i++) - reg_w(gspca_dev, 0x84, reg84_sn9c325, - sizeof reg84_sn9c325); - reg_w1(gspca_dev, 0x9a, 0x0a); - reg_w1(gspca_dev, 0x99, 0x60); - break; - default: - reg_w(gspca_dev, 0x20, regsn20, sizeof regsn20); - for (i = 0; i < 8; i++) - reg_w(gspca_dev, 0x84, reg84, sizeof reg84); + reg_w(gspca_dev, 0x20, gamma_def, sizeof gamma_def); + for (i = 0; i < 8; i++) + reg_w(gspca_dev, 0x84, reg84, sizeof reg84); reg_w1(gspca_dev, 0x9a, 0x08); reg_w1(gspca_dev, 0x99, 0x59); - break; - } mode = gspca_dev->cam.cam_mode[(int) gspca_dev->curr_mode].priv; if (mode) @@ -1272,8 +1295,18 @@ static void sd_start(struct gspca_dev *gspca_dev) reg_w1(gspca_dev, 0x17, reg17); reg_w1(gspca_dev, 0x01, reg1); - setbrightness(gspca_dev); - setcontrast(gspca_dev); + switch (sd->sensor) { + case SENSOR_HV7131R: + case SENSOR_MI0360: + case SENSOR_MO4000: + case SENSOR_OM6802: + setbrightness(gspca_dev); + setcontrast(gspca_dev); + break; + default: /* OV76xx */ + setbrightcont(gspca_dev); + break; + } setautogain(gspca_dev); } @@ -1311,7 +1344,7 @@ static void sd_stopN(struct gspca_dev *gspca_dev) reg_w1(gspca_dev, 0x17, sn9c1xx[0x17]); reg_w1(gspca_dev, 0x01, sn9c1xx[1]); reg_w1(gspca_dev, 0x01, data); - reg_w1(gspca_dev, 0xf1, 0x01); + reg_w1(gspca_dev, 0xf1, sd->regf1); } static void sd_stop0(struct gspca_dev *gspca_dev) @@ -1409,72 +1442,24 @@ static void sd_pkt_scan(struct gspca_dev *gspca_dev, gspca_frame_add(gspca_dev, INTER_PACKET, frame, data, len); } -static unsigned int getexposure(struct gspca_dev *gspca_dev) -{ - struct sd *sd = (struct sd *) gspca_dev; - __u8 hexpo, mexpo, lexpo; - - switch (sd->sensor) { - case SENSOR_HV7131R: - /* read sensor exposure */ - i2c_r5(gspca_dev, 0x25); - return (gspca_dev->usb_buf[0] << 16) - | (gspca_dev->usb_buf[1] << 8) - | gspca_dev->usb_buf[2]; - case SENSOR_MI0360: - /* read sensor exposure */ - i2c_r5(gspca_dev, 0x09); - return (gspca_dev->usb_buf[0] << 8) - | gspca_dev->usb_buf[1]; - default: -/* case SENSOR_MO4000: */ - i2c_r5(gspca_dev, 0x0e); - hexpo = 0; /* gspca_dev->usb_buf[1] & 0x07; */ - mexpo = 0x40; /* gspca_dev->usb_buf[2] & 0xff; */ - lexpo = (gspca_dev->usb_buf[1] & 0x30) >> 4; - PDEBUG(D_CONF, "exposure %d", - (hexpo << 10) | (mexpo << 2) | lexpo); - return (hexpo << 10) | (mexpo << 2) | lexpo; -#if 0 -/*jfm: not called*/ -/* case SENSOR_OV7648: * jfm: is it ok for 7648? */ -/* case SENSOR_OV7660: */ - /* read sensor exposure */ - i2c_r5(gspca_dev, 0x04); - hexpo = gspca_dev->usb_buf[3] & 0x2f; - lexpo = gspca_dev->usb_buf[0] & 0x02; - i2c_r5(gspca_dev, 0x08); - mexpo = gspca_dev->usb_buf[2]; - return (hexpo << 10) | (mexpo << 2) | lexpo; -#endif - } - /* not reached */ -} - -static void getbrightness(struct gspca_dev *gspca_dev) -{ - struct sd *sd = (struct sd *) gspca_dev; - - /* hardcoded registers seem not readable */ - switch (sd->sensor) { - case SENSOR_HV7131R: - sd->brightness = getexposure(gspca_dev) >> 4; - break; - case SENSOR_MI0360: - case SENSOR_MO4000: - case SENSOR_OM6802: - sd->brightness = getexposure(gspca_dev) << 4; - break; - } -} - static int sd_setbrightness(struct gspca_dev *gspca_dev, __s32 val) { struct sd *sd = (struct sd *) gspca_dev; sd->brightness = val; - if (gspca_dev->streaming) - setbrightness(gspca_dev); + if (gspca_dev->streaming) { + switch (sd->sensor) { + case SENSOR_HV7131R: + case SENSOR_MI0360: + case SENSOR_MO4000: + case SENSOR_OM6802: + setbrightness(gspca_dev); + break; + default: /* OV76xx */ + setbrightcont(gspca_dev); + break; + } + } return 0; } @@ -1482,7 +1467,6 @@ static int sd_getbrightness(struct gspca_dev *gspca_dev, __s32 *val) { struct sd *sd = (struct sd *) gspca_dev; - getbrightness(gspca_dev); *val = sd->brightness; return 0; } @@ -1492,8 +1476,19 @@ static int sd_setcontrast(struct gspca_dev *gspca_dev, __s32 val) struct sd *sd = (struct sd *) gspca_dev; sd->contrast = val; - if (gspca_dev->streaming) - setcontrast(gspca_dev); + if (gspca_dev->streaming) { + switch (sd->sensor) { + case SENSOR_HV7131R: + case SENSOR_MI0360: + case SENSOR_MO4000: + case SENSOR_OM6802: + setcontrast(gspca_dev); + break; + default: /* OV76xx */ + setbrightcont(gspca_dev); + break; + } + } return 0; } -- cgit v0.10.2 From d55b83d3c4558d0d118bf20ef3f1fa65b1c75c3d Mon Sep 17 00:00:00 2001 From: Jean-Francois Moine Date: Wed, 3 Sep 2008 16:48:01 -0300 Subject: V4L/DVB (8710): gspca: Bad color control in sonixj. Signed-off-by: Jean-Francois Moine Signed-off-by: Mauro Carvalho Chehab diff --git a/drivers/media/video/gspca/sonixj.c b/drivers/media/video/gspca/sonixj.c index b17aaa4..c34e02d 100644 --- a/drivers/media/video/gspca/sonixj.c +++ b/drivers/media/video/gspca/sonixj.c @@ -794,7 +794,7 @@ static int configure_gpio(struct gspca_dev *gspca_dev, switch (sd->sensor) { case SENSOR_OM6802: - reg_w1(gspca_dev, 0x02, 0x71); + reg_w1(gspca_dev, 0x02, 0x73); /* was 71 */ reg_w1(gspca_dev, 0x01, 0x42); reg_w1(gspca_dev, 0x17, 0x64); reg_w1(gspca_dev, 0x01, 0x42); @@ -1056,7 +1056,7 @@ static unsigned int setexposure(struct gspca_dev *gspca_dev, expo = 0x0001; gainOm[3] = expo >> 2; i2c_w8(gspca_dev, gainOm); - reg_w1(gspca_dev, 0x96, expo >> 5); + reg_w1(gspca_dev, 0x96, (expo >> 5) & 0x1f); PDEBUG(D_CONF, "set exposure %d", gainOm[3]); break; } @@ -1138,11 +1138,13 @@ static void setcolors(struct gspca_dev *gspca_dev) int colour; colour = sd->colors - 128; - if (colour > 0) + if (colour > 0) { data = (colour + 32) & 0x7f; /* blue */ - else + reg_w1(gspca_dev, 0x06, data); + } else { data = (-colour + 32) & 0x7f; /* red */ - reg_w1(gspca_dev, 0x05, data); + reg_w1(gspca_dev, 0x05, data); + } } static void setautogain(struct gspca_dev *gspca_dev) -- cgit v0.10.2 From 4a18625e88efef2b5a21695edcb2b21d98fdf71b Mon Sep 17 00:00:00 2001 From: Jean-Francois Moine Date: Wed, 3 Sep 2008 16:48:02 -0300 Subject: V4L/DVB (8711): gspca: Bad controls and quantization table of pac7311. Patch adapted from a gspca v1 patch by Thomas Kaiser. Signed-off-by: Jean-Francois Moine Signed-off-by: Mauro Carvalho Chehab diff --git a/drivers/media/video/gspca/pac7311.c b/drivers/media/video/gspca/pac7311.c index a89cc9f..e4f56e0 100644 --- a/drivers/media/video/gspca/pac7311.c +++ b/drivers/media/video/gspca/pac7311.c @@ -42,6 +42,7 @@ struct sd { unsigned char autogain; __u8 hflip; __u8 vflip; + __u8 qindex; char tosof; /* number of bytes before next start of frame */ signed char ag_cnt; @@ -462,6 +463,9 @@ static int sd_config(struct gspca_dev *gspca_dev, sd->contrast = CONTRAST_DEF; sd->colors = COLOR_DEF; sd->autogain = AUTOGAIN_DEF; + sd->hflip = HFLIP_DEF; + sd->vflip = VFLIP_DEF; + sd->qindex = 3; sd->ag_cnt = -1; return 0; } @@ -505,6 +509,7 @@ static void setbrightness(struct gspca_dev *gspca_dev) /*jfm: inverted?*/ brightness = BRIGHTNESS_MAX - sd->brightness; reg_w(gspca_dev, 0xff, 0x04); + reg_w(gspca_dev, 0x0e, 0x00); reg_w(gspca_dev, 0x0f, brightness); /* load registers to sensor (Bit 0, auto clear) */ reg_w(gspca_dev, 0x11, 0x01); @@ -520,7 +525,7 @@ static void setcontrast(struct gspca_dev *gspca_dev) return; } reg_w(gspca_dev, 0xff, 0x01); - reg_w(gspca_dev, 0x80, sd->contrast); + reg_w(gspca_dev, 0x10, sd->contrast); /* load registers to sensor (Bit 0, auto clear) */ reg_w(gspca_dev, 0x11, 0x01); } @@ -549,7 +554,7 @@ static void setcolors(struct gspca_dev *gspca_dev) return; } reg_w(gspca_dev, 0xff, 0x01); - reg_w(gspca_dev, 0x10, sd->colors); + reg_w(gspca_dev, 0x80, sd->colors); /* load registers to sensor (Bit 0, auto clear) */ reg_w(gspca_dev, 0x11, 0x01); PDEBUG(D_CONF|D_STREAM, "color: %i", sd->colors); @@ -583,7 +588,7 @@ static void sethvflip(struct gspca_dev *gspca_dev) /* this function is called at open time */ static int sd_open(struct gspca_dev *gspca_dev) { - reg_w(gspca_dev, 0x78, 0x00); /* Turn on LED */ + reg_w(gspca_dev, 0x78, 0x44); /* Turn on LED */ return 0; } @@ -612,27 +617,24 @@ static void sd_start(struct gspca_dev *gspca_dev) reg_w(gspca_dev, 0x08, 0x09); reg_w(gspca_dev, 0x17, 0x20); reg_w(gspca_dev, 0x1b, 0x00); -/* reg_w(gspca_dev, 0x80, 0x69); */ reg_w(gspca_dev, 0x87, 0x10); break; case 1: /* 320x240 pac7311 */ reg_w(gspca_dev, 0xff, 0x04); - reg_w(gspca_dev, 0x02, 0x03); + reg_w(gspca_dev, 0x02, 0x07); reg_w(gspca_dev, 0xff, 0x01); reg_w(gspca_dev, 0x08, 0x09); reg_w(gspca_dev, 0x17, 0x30); -/* reg_w(gspca_dev, 0x80, 0x3f); */ reg_w(gspca_dev, 0x87, 0x11); break; case 0: /* 640x480 */ if (sd->sensor == SENSOR_PAC7302) break; reg_w(gspca_dev, 0xff, 0x04); - reg_w(gspca_dev, 0x02, 0x03); + reg_w(gspca_dev, 0x02, 0x07); reg_w(gspca_dev, 0xff, 0x01); reg_w(gspca_dev, 0x08, 0x08); reg_w(gspca_dev, 0x17, 0x00); -/* reg_w(gspca_dev, 0x80, 0x1c); */ reg_w(gspca_dev, 0x87, 0x12); break; } @@ -645,8 +647,8 @@ static void sd_start(struct gspca_dev *gspca_dev) reg_w(gspca_dev, 0xff, 0x01); reg_w(gspca_dev, 0x78, 0x01); } else { - reg_w(gspca_dev, 0x78, 0x04); - reg_w(gspca_dev, 0x78, 0x05); + reg_w(gspca_dev, 0x78, 0x44); + reg_w(gspca_dev, 0x78, 0x45); } } @@ -666,7 +668,7 @@ static void sd_stopN(struct gspca_dev *gspca_dev) reg_w(gspca_dev, 0x2a, 0x0e); reg_w(gspca_dev, 0xff, 0x01); reg_w(gspca_dev, 0x3e, 0x20); - reg_w(gspca_dev, 0x78, 0x04); /* Bit_0=start stream, Bit_7=LED */ + reg_w(gspca_dev, 0x78, 0x44); /* Bit_0=start stream, Bit_7=LED */ reg_w(gspca_dev, 0x78, 0x44); /* Bit_0=start stream, Bit_7=LED */ reg_w(gspca_dev, 0x78, 0x44); /* Bit_0=start stream, Bit_7=LED */ } @@ -757,7 +759,7 @@ static void sd_pkt_scan(struct gspca_dev *gspca_dev, if (sd->tosof > LUM_OFFSET) sd->lum_sum += data[-LUM_OFFSET]; sd->tosof = 0; - jpeg_put_header(gspca_dev, frame, 1, 0x21); + jpeg_put_header(gspca_dev, frame, sd->qindex, 0x21); } for (i = 0; i < len; i++) { @@ -777,7 +779,7 @@ static void sd_pkt_scan(struct gspca_dev *gspca_dev, sd->tosof = -len; break; } - jpeg_put_header(gspca_dev, frame, 1, 0x21); + jpeg_put_header(gspca_dev, frame, sd->qindex, 0x21); break; } } -- cgit v0.10.2 From 759aa3c21ebbab6cc00fc4aebd09b3a7d63715d1 Mon Sep 17 00:00:00 2001 From: Jean-Francois Moine Date: Wed, 3 Sep 2008 16:48:03 -0300 Subject: V4L/DVB (8712): gspca: Bad start of sonixj webcams since changeset a8779025e7e8. Signed-off-by: Jean-Francois Moine Signed-off-by: Mauro Carvalho Chehab diff --git a/drivers/media/video/gspca/sonixj.c b/drivers/media/video/gspca/sonixj.c index c34e02d..6673a3e 100644 --- a/drivers/media/video/gspca/sonixj.c +++ b/drivers/media/video/gspca/sonixj.c @@ -59,7 +59,6 @@ struct sd { #define SENSOR_OV7648 5 #define SENSOR_OV7660 6 unsigned char i2c_base; - __u8 regf1; }; /* V4L2 controls supported by the driver */ @@ -929,7 +928,6 @@ static int sd_config(struct gspca_dev *gspca_dev, sd->bridge = id->driver_info >> 16; sd->sensor = id->driver_info >> 8; sd->i2c_base = id->driver_info; - sd->regf1 = 0; /*jfm: was 1 in v1*/ sd->qindex = 4; /* set the quantization table */ sd->brightness = BRIGHTNESS_DEF; @@ -982,7 +980,7 @@ static int sd_open(struct gspca_dev *gspca_dev) break; } - reg_w1(gspca_dev, 0xf1, sd->regf1); + reg_w1(gspca_dev, 0xf1, 0x01); return 0; } @@ -1346,7 +1344,7 @@ static void sd_stopN(struct gspca_dev *gspca_dev) reg_w1(gspca_dev, 0x17, sn9c1xx[0x17]); reg_w1(gspca_dev, 0x01, sn9c1xx[1]); reg_w1(gspca_dev, 0x01, data); - reg_w1(gspca_dev, 0xf1, sd->regf1); + reg_w1(gspca_dev, 0xf1, 0x00); } static void sd_stop0(struct gspca_dev *gspca_dev) -- cgit v0.10.2 From 9c5f70f248ccce6d943904e6da687c6ec062f072 Mon Sep 17 00:00:00 2001 From: Jean-Francois Moine Date: Wed, 3 Sep 2008 16:48:04 -0300 Subject: V4L/DVB (8713): gspca: Bad color control again in sonixj. Signed-off-by: Jean-Francois Moine Signed-off-by: Mauro Carvalho Chehab diff --git a/drivers/media/video/gspca/sonixj.c b/drivers/media/video/gspca/sonixj.c index 6673a3e..19c9791 100644 --- a/drivers/media/video/gspca/sonixj.c +++ b/drivers/media/video/gspca/sonixj.c @@ -108,9 +108,9 @@ static struct ctrl sd_ctrls[] = { .type = V4L2_CTRL_TYPE_INTEGER, .name = "Color", .minimum = 0, - .maximum = 255, + .maximum = 64, .step = 1, -#define COLOR_DEF 127 +#define COLOR_DEF 32 .default_value = COLOR_DEF, }, .set = sd_setcolors, @@ -1132,17 +1132,18 @@ static void setcontrast(struct gspca_dev *gspca_dev) static void setcolors(struct gspca_dev *gspca_dev) { struct sd *sd = (struct sd *) gspca_dev; - __u8 data; - int colour; + __u8 blue, red; - colour = sd->colors - 128; - if (colour > 0) { - data = (colour + 32) & 0x7f; /* blue */ - reg_w1(gspca_dev, 0x06, data); + if (sd->colors >= 32) { + red = 32 + (sd->colors - 32) / 2; + blue = 64 - sd->colors; } else { - data = (-colour + 32) & 0x7f; /* red */ - reg_w1(gspca_dev, 0x05, data); + red = sd->colors; + blue = 32 + (32 - sd->colors) / 2; } + reg_w1(gspca_dev, 0x05, red); +/* reg_w1(gspca_dev, 0x07, 32); */ + reg_w1(gspca_dev, 0x06, blue); } static void setautogain(struct gspca_dev *gspca_dev) -- cgit v0.10.2 From 4f30f6cf6b1baf2d19f6b575c4486ae6dc0c2a00 Mon Sep 17 00:00:00 2001 From: Jean-Francois Moine Date: Wed, 3 Sep 2008 16:48:05 -0300 Subject: V4L/DVB (8714): gspca: Bad start of sn9c110 and sensor om6802. Signed-off-by: Jean-Francois Moine Signed-off-by: Mauro Carvalho Chehab diff --git a/drivers/media/video/gspca/sonixj.c b/drivers/media/video/gspca/sonixj.c index 19c9791..7860061 100644 --- a/drivers/media/video/gspca/sonixj.c +++ b/drivers/media/video/gspca/sonixj.c @@ -793,7 +793,7 @@ static int configure_gpio(struct gspca_dev *gspca_dev, switch (sd->sensor) { case SENSOR_OM6802: - reg_w1(gspca_dev, 0x02, 0x73); /* was 71 */ + reg_w1(gspca_dev, 0x02, 0x71); reg_w1(gspca_dev, 0x01, 0x42); reg_w1(gspca_dev, 0x17, 0x64); reg_w1(gspca_dev, 0x01, 0x42); -- cgit v0.10.2 From 142346bf9f2410b32cd219cf3f70a85ac56d5b85 Mon Sep 17 00:00:00 2001 From: Jean-Francois Moine Date: Wed, 3 Sep 2008 16:48:07 -0300 Subject: V4L/DVB (8715): gspca: Change the name of some webcam in the gspca doc. Signed-off-by: Jean-Francois Moine Signed-off-by: Mauro Carvalho Chehab diff --git a/Documentation/video4linux/gspca.txt b/Documentation/video4linux/gspca.txt index c7fc9fa..2dd2f77 100644 --- a/Documentation/video4linux/gspca.txt +++ b/Documentation/video4linux/gspca.txt @@ -88,14 +88,14 @@ zc3xx 0471:0325 Philips SPC 200 NC zc3xx 0471:0326 Philips SPC 300 NC sonixj 0471:0327 Philips SPC 600 NC sonixj 0471:0328 Philips SPC 700 NC -zc3xx 0471:032d Philips spc210nc -zc3xx 0471:032e Philips spc315nc -sonixj 0471:0330 Philips SPC 710NC +zc3xx 0471:032d Philips SPC 210 NC +zc3xx 0471:032e Philips SPC 315 NC +sonixj 0471:0330 Philips SPC 710 NC spca501 0497:c001 Smile International sunplus 04a5:3003 Benq DC 1300 sunplus 04a5:3008 Benq DC 1500 -sunplus 04a5:300a Benq DC3410 -spca500 04a5:300c Benq DC1016 +sunplus 04a5:300a Benq DC 3410 +spca500 04a5:300c Benq DC 1016 sunplus 04f1:1001 JVC GC A50 spca561 04fc:0561 Flexcam 100 sunplus 04fc:500c Sunplus CA500C @@ -175,18 +175,18 @@ sunplus 08ca:2060 Aiptek PocketDV5300 tv8532 0923:010f ICM532 cams mars 093a:050f Mars-Semi Pc-Camera pac207 093a:2460 PAC207 Qtec Webcam 100 -pac207 093a:2463 Philips spc200nc pac207 +pac207 093a:2463 Philips SPC 220 NC pac207 093a:2464 Labtec Webcam 1200 pac207 093a:2468 PAC207 pac207 093a:2470 Genius GF112 -pac207 093a:2471 PAC207 Genius VideoCam ge111 -pac207 093a:2472 PAC207 Genius VideoCam ge110 +pac207 093a:2471 Genius VideoCam ge111 +pac207 093a:2472 Genius VideoCam ge110 pac7311 093a:2600 PAC7311 Typhoon -pac7311 093a:2601 PAC7311 Phillips SPC610NC +pac7311 093a:2601 Philips SPC 610 NC pac7311 093a:2603 PAC7312 -pac7311 093a:2608 PAC7311 Trust WB-3300p -pac7311 093a:260e PAC7311 Gigaware VGA PC Camera, Trust WB-3350p, SIGMA cam 2350 -pac7311 093a:260f PAC7311 SnakeCam +pac7311 093a:2608 Trust WB-3300p +pac7311 093a:260e Gigaware VGA PC Camera, Trust WB-3350p, SIGMA cam 2350 +pac7311 093a:260f SnakeCam pac7311 093a:2621 PAC731x zc3xx 0ac8:0302 Z-star Vimicro zc0302 vc032x 0ac8:0321 Vimicro generic vc0321 @@ -235,7 +235,7 @@ zc3xx 10fd:0128 Typhoon Webshot II USB 300k 0x0128 spca561 10fd:7e50 FlyCam Usb 100 zc3xx 10fd:8050 Typhoon Webshot II USB 300k spca501 1776:501c Arowana 300K CMOS Camera -t613 17a1:0128 T613/TAS5130A +t613 17a1:0128 TASCORP JPEG Webcam, NGS Cyclops vc032x 17ef:4802 Lenovo Vc0323+MI1310_SOC pac207 2001:f115 D-Link DSB-C120 spca500 2899:012c Toptro Industrial -- cgit v0.10.2 From 5b064da80831500a6ac6ea501d2d0cb5e8323cc7 Mon Sep 17 00:00:00 2001 From: Jean-Francois Moine Date: Wed, 3 Sep 2008 16:48:08 -0300 Subject: V4L/DVB (8716): gspca: Bad start of sn9c110 and sensor ov7630. Signed-off-by: Jean-Francois Moine Signed-off-by: Mauro Carvalho Chehab diff --git a/drivers/media/video/gspca/sonixj.c b/drivers/media/video/gspca/sonixj.c index 7860061..e0ba50c 100644 --- a/drivers/media/video/gspca/sonixj.c +++ b/drivers/media/video/gspca/sonixj.c @@ -1248,7 +1248,7 @@ static void sd_start(struct gspca_dev *gspca_dev) case SENSOR_OV7630: ov7630_InitSensor(gspca_dev); reg17 = 0xe2; - reg1 = 0x40; + reg1 = 0x44; break; case SENSOR_OV7648: ov7648_InitSensor(gspca_dev); -- cgit v0.10.2 From 5d05294ac8f6b5d592ee3379fbddd0fb9d1b4c87 Mon Sep 17 00:00:00 2001 From: Jean-Francois Moine Date: Wed, 3 Sep 2008 16:48:09 -0300 Subject: V4L/DVB (8717): gspca: Frame buffer too small for small resolutions (sonixj and t613). Signed-off-by: Jean-Francois Moine Signed-off-by: Mauro Carvalho Chehab diff --git a/drivers/media/video/gspca/sonixj.c b/drivers/media/video/gspca/sonixj.c index e0ba50c..11a29a9 100644 --- a/drivers/media/video/gspca/sonixj.c +++ b/drivers/media/video/gspca/sonixj.c @@ -135,7 +135,7 @@ static struct ctrl sd_ctrls[] = { static struct v4l2_pix_format vga_mode[] = { {160, 120, V4L2_PIX_FMT_JPEG, V4L2_FIELD_NONE, .bytesperline = 160, - .sizeimage = 160 * 120 * 3 / 8 + 590, + .sizeimage = 160 * 120 * 4 / 8 + 590, .colorspace = V4L2_COLORSPACE_JPEG, .priv = 2}, {320, 240, V4L2_PIX_FMT_JPEG, V4L2_FIELD_NONE, diff --git a/drivers/media/video/gspca/t613.c b/drivers/media/video/gspca/t613.c index 91b555c..fd6918e 100644 --- a/drivers/media/video/gspca/t613.c +++ b/drivers/media/video/gspca/t613.c @@ -233,7 +233,7 @@ static char *effects_control[] = { static struct v4l2_pix_format vga_mode_t16[] = { {160, 120, V4L2_PIX_FMT_JPEG, V4L2_FIELD_NONE, .bytesperline = 160, - .sizeimage = 160 * 120 * 3 / 8 + 590, + .sizeimage = 160 * 120 * 4 / 8 + 590, .colorspace = V4L2_COLORSPACE_JPEG, .priv = 4}, {176, 144, V4L2_PIX_FMT_JPEG, V4L2_FIELD_NONE, -- cgit v0.10.2 From 6a709749228c5f76f128c69c16f39a52d639bd96 Mon Sep 17 00:00:00 2001 From: Jean-Francois Moine Date: Wed, 3 Sep 2008 16:48:10 -0300 Subject: V4L/DVB (8718): gspca: suspend/resume added. Signed-off-by: Jean-Francois Moine Signed-off-by: Mauro Carvalho Chehab diff --git a/drivers/media/video/gspca/conex.c b/drivers/media/video/gspca/conex.c index cd3a3f5..739ef557 100644 --- a/drivers/media/video/gspca/conex.c +++ b/drivers/media/video/gspca/conex.c @@ -1026,6 +1026,10 @@ static struct usb_driver sd_driver = { .id_table = device_table, .probe = sd_probe, .disconnect = gspca_disconnect, +#ifdef CONFIG_PM + .suspend = gspca_suspend, + .resume = gspca_resume, +#endif }; /* -- module insert / remove -- */ diff --git a/drivers/media/video/gspca/etoms.c b/drivers/media/video/gspca/etoms.c index ca23c3f..a3cccab 100644 --- a/drivers/media/video/gspca/etoms.c +++ b/drivers/media/video/gspca/etoms.c @@ -926,6 +926,10 @@ static struct usb_driver sd_driver = { .id_table = device_table, .probe = sd_probe, .disconnect = gspca_disconnect, +#ifdef CONFIG_PM + .suspend = gspca_suspend, + .resume = gspca_resume, +#endif }; /* -- module insert / remove -- */ diff --git a/drivers/media/video/gspca/gspca.c b/drivers/media/video/gspca/gspca.c index 15d302b..2f7bf26 100644 --- a/drivers/media/video/gspca/gspca.c +++ b/drivers/media/video/gspca/gspca.c @@ -114,7 +114,8 @@ static void fill_frame(struct gspca_dev *gspca_dev, cam_pkt_op pkt_scan; if (urb->status != 0) { - PDEBUG(D_ERR|D_PACK, "urb status: %d", urb->status); + if (!gspca_dev->frozen) + PDEBUG(D_ERR|D_PACK, "urb status: %d", urb->status); return; /* disconnection ? */ } pkt_scan = gspca_dev->sd_desc->pkt_scan; @@ -1808,6 +1809,33 @@ void gspca_disconnect(struct usb_interface *intf) } EXPORT_SYMBOL(gspca_disconnect); +#ifdef CONFIG_PM +int gspca_suspend(struct usb_interface *intf, pm_message_t message) +{ + struct gspca_dev *gspca_dev = usb_get_intfdata(intf); + + if (!gspca_dev->streaming) + return 0; + gspca_dev->frozen = 1; /* avoid urb error messages */ + gspca_dev->sd_desc->stopN(gspca_dev); + destroy_urbs(gspca_dev); + gspca_set_alt0(gspca_dev); + gspca_dev->sd_desc->stop0(gspca_dev); + return 0; +} +EXPORT_SYMBOL(gspca_suspend); + +int gspca_resume(struct usb_interface *intf) +{ + struct gspca_dev *gspca_dev = usb_get_intfdata(intf); + + gspca_dev->frozen = 0; + if (!gspca_dev->streaming) + return 0; + return gspca_init_transfer(gspca_dev); +} +EXPORT_SYMBOL(gspca_resume); +#endif /* -- cam driver utility functions -- */ /* auto gain and exposure algorithm based on the knee algorithm described here: diff --git a/drivers/media/video/gspca/gspca.h b/drivers/media/video/gspca/gspca.h index 5cb5845..2596568 100644 --- a/drivers/media/video/gspca/gspca.h +++ b/drivers/media/video/gspca/gspca.h @@ -154,6 +154,9 @@ struct gspca_dev { struct mutex queue_lock; /* ISOC queue protection */ __u32 sequence; /* frame sequence number */ char streaming; +#ifdef CONFIG_PM + char frozen; /* suspend - resume */ +#endif char users; /* number of opens */ char present; /* device connected */ char nbufread; /* number of buffers for read() */ @@ -173,6 +176,10 @@ struct gspca_frame *gspca_frame_add(struct gspca_dev *gspca_dev, struct gspca_frame *frame, const __u8 *data, int len); +#ifdef CONFIG_PM +int gspca_suspend(struct usb_interface *intf, pm_message_t message); +int gspca_resume(struct usb_interface *intf); +#endif int gspca_auto_gain_n_exposure(struct gspca_dev *gspca_dev, int avg_lum, int desired_avg_lum, int deadzone, int gain_knee, int exposure_knee); #endif /* GSPCAV2_H */ diff --git a/drivers/media/video/gspca/mars.c b/drivers/media/video/gspca/mars.c index 21c4ee5..d7e2095 100644 --- a/drivers/media/video/gspca/mars.c +++ b/drivers/media/video/gspca/mars.c @@ -439,6 +439,10 @@ static struct usb_driver sd_driver = { .id_table = device_table, .probe = sd_probe, .disconnect = gspca_disconnect, +#ifdef CONFIG_PM + .suspend = gspca_suspend, + .resume = gspca_resume, +#endif }; /* -- module insert / remove -- */ diff --git a/drivers/media/video/gspca/ov519.c b/drivers/media/video/gspca/ov519.c index b4f00ec..c132f8d 100644 --- a/drivers/media/video/gspca/ov519.c +++ b/drivers/media/video/gspca/ov519.c @@ -2132,6 +2132,10 @@ static struct usb_driver sd_driver = { .id_table = device_table, .probe = sd_probe, .disconnect = gspca_disconnect, +#ifdef CONFIG_PM + .suspend = gspca_suspend, + .resume = gspca_resume, +#endif }; /* -- module insert / remove -- */ diff --git a/drivers/media/video/gspca/pac207.c b/drivers/media/video/gspca/pac207.c index cee45b0..d9668f4 100644 --- a/drivers/media/video/gspca/pac207.c +++ b/drivers/media/video/gspca/pac207.c @@ -596,6 +596,10 @@ static struct usb_driver sd_driver = { .id_table = device_table, .probe = sd_probe, .disconnect = gspca_disconnect, +#ifdef CONFIG_PM + .suspend = gspca_suspend, + .resume = gspca_resume, +#endif }; /* -- module insert / remove -- */ diff --git a/drivers/media/video/gspca/pac7311.c b/drivers/media/video/gspca/pac7311.c index e4f56e0..4cc9379 100644 --- a/drivers/media/video/gspca/pac7311.c +++ b/drivers/media/video/gspca/pac7311.c @@ -936,6 +936,10 @@ static struct usb_driver sd_driver = { .id_table = device_table, .probe = sd_probe, .disconnect = gspca_disconnect, +#ifdef CONFIG_PM + .suspend = gspca_suspend, + .resume = gspca_resume, +#endif }; /* -- module insert / remove -- */ diff --git a/drivers/media/video/gspca/sonixb.c b/drivers/media/video/gspca/sonixb.c index 11210c7..e535ced 100644 --- a/drivers/media/video/gspca/sonixb.c +++ b/drivers/media/video/gspca/sonixb.c @@ -1231,6 +1231,10 @@ static struct usb_driver sd_driver = { .id_table = device_table, .probe = sd_probe, .disconnect = gspca_disconnect, +#ifdef CONFIG_PM + .suspend = gspca_suspend, + .resume = gspca_resume, +#endif }; /* -- module insert / remove -- */ diff --git a/drivers/media/video/gspca/sonixj.c b/drivers/media/video/gspca/sonixj.c index 11a29a9..0d46776 100644 --- a/drivers/media/video/gspca/sonixj.c +++ b/drivers/media/video/gspca/sonixj.c @@ -1617,6 +1617,10 @@ static struct usb_driver sd_driver = { .id_table = device_table, .probe = sd_probe, .disconnect = gspca_disconnect, +#ifdef CONFIG_PM + .suspend = gspca_suspend, + .resume = gspca_resume, +#endif }; /* -- module insert / remove -- */ diff --git a/drivers/media/video/gspca/spca500.c b/drivers/media/video/gspca/spca500.c index 17fe2c2..5a20385fb 100644 --- a/drivers/media/video/gspca/spca500.c +++ b/drivers/media/video/gspca/spca500.c @@ -1093,6 +1093,10 @@ static struct usb_driver sd_driver = { .id_table = device_table, .probe = sd_probe, .disconnect = gspca_disconnect, +#ifdef CONFIG_PM + .suspend = gspca_suspend, + .resume = gspca_resume, +#endif }; /* -- module insert / remove -- */ diff --git a/drivers/media/video/gspca/spca501.c b/drivers/media/video/gspca/spca501.c index 51a3c34..525f1b3 100644 --- a/drivers/media/video/gspca/spca501.c +++ b/drivers/media/video/gspca/spca501.c @@ -2154,6 +2154,10 @@ static struct usb_driver sd_driver = { .id_table = device_table, .probe = sd_probe, .disconnect = gspca_disconnect, +#ifdef CONFIG_PM + .suspend = gspca_suspend, + .resume = gspca_resume, +#endif }; /* -- module insert / remove -- */ diff --git a/drivers/media/video/gspca/spca505.c b/drivers/media/video/gspca/spca505.c index eda29d6..8f00558 100644 --- a/drivers/media/video/gspca/spca505.c +++ b/drivers/media/video/gspca/spca505.c @@ -855,6 +855,10 @@ static struct usb_driver sd_driver = { .id_table = device_table, .probe = sd_probe, .disconnect = gspca_disconnect, +#ifdef CONFIG_PM + .suspend = gspca_suspend, + .resume = gspca_resume, +#endif }; /* -- module insert / remove -- */ diff --git a/drivers/media/video/gspca/spca506.c b/drivers/media/video/gspca/spca506.c index f622fa7..ae77248 100644 --- a/drivers/media/video/gspca/spca506.c +++ b/drivers/media/video/gspca/spca506.c @@ -772,6 +772,10 @@ static struct usb_driver sd_driver = { .id_table = device_table, .probe = sd_probe, .disconnect = gspca_disconnect, +#ifdef CONFIG_PM + .suspend = gspca_suspend, + .resume = gspca_resume, +#endif }; /* -- module insert / remove -- */ diff --git a/drivers/media/video/gspca/spca508.c b/drivers/media/video/gspca/spca508.c index 699340c..7b38c4e 100644 --- a/drivers/media/video/gspca/spca508.c +++ b/drivers/media/video/gspca/spca508.c @@ -1667,6 +1667,10 @@ static struct usb_driver sd_driver = { .id_table = device_table, .probe = sd_probe, .disconnect = gspca_disconnect, +#ifdef CONFIG_PM + .suspend = gspca_suspend, + .resume = gspca_resume, +#endif }; /* -- module insert / remove -- */ diff --git a/drivers/media/video/gspca/spca561.c b/drivers/media/video/gspca/spca561.c index ec575f5..b6a013f 100644 --- a/drivers/media/video/gspca/spca561.c +++ b/drivers/media/video/gspca/spca561.c @@ -1184,6 +1184,10 @@ static struct usb_driver sd_driver = { .id_table = device_table, .probe = sd_probe, .disconnect = gspca_disconnect, +#ifdef CONFIG_PM + .suspend = gspca_suspend, + .resume = gspca_resume, +#endif }; /* -- module insert / remove -- */ diff --git a/drivers/media/video/gspca/stk014.c b/drivers/media/video/gspca/stk014.c index 16219cf..387a8cf 100644 --- a/drivers/media/video/gspca/stk014.c +++ b/drivers/media/video/gspca/stk014.c @@ -564,6 +564,10 @@ static struct usb_driver sd_driver = { .id_table = device_table, .probe = sd_probe, .disconnect = gspca_disconnect, +#ifdef CONFIG_PM + .suspend = gspca_suspend, + .resume = gspca_resume, +#endif }; /* -- module insert / remove -- */ diff --git a/drivers/media/video/gspca/sunplus.c b/drivers/media/video/gspca/sunplus.c index 54efa48..c935384 100644 --- a/drivers/media/video/gspca/sunplus.c +++ b/drivers/media/video/gspca/sunplus.c @@ -1456,6 +1456,10 @@ static struct usb_driver sd_driver = { .id_table = device_table, .probe = sd_probe, .disconnect = gspca_disconnect, +#ifdef CONFIG_PM + .suspend = gspca_suspend, + .resume = gspca_resume, +#endif }; /* -- module insert / remove -- */ diff --git a/drivers/media/video/gspca/t613.c b/drivers/media/video/gspca/t613.c index fd6918e..357a2ed 100644 --- a/drivers/media/video/gspca/t613.c +++ b/drivers/media/video/gspca/t613.c @@ -1014,6 +1014,10 @@ static struct usb_driver sd_driver = { .id_table = device_table, .probe = sd_probe, .disconnect = gspca_disconnect, +#ifdef CONFIG_PM + .suspend = gspca_suspend, + .resume = gspca_resume, +#endif }; /* -- module insert / remove -- */ diff --git a/drivers/media/video/gspca/tv8532.c b/drivers/media/video/gspca/tv8532.c index 1ff8ba2..d227362 100644 --- a/drivers/media/video/gspca/tv8532.c +++ b/drivers/media/video/gspca/tv8532.c @@ -644,6 +644,10 @@ static struct usb_driver sd_driver = { .id_table = device_table, .probe = sd_probe, .disconnect = gspca_disconnect, +#ifdef CONFIG_PM + .suspend = gspca_suspend, + .resume = gspca_resume, +#endif }; /* -- module insert / remove -- */ diff --git a/drivers/media/video/gspca/vc032x.c b/drivers/media/video/gspca/vc032x.c index f4a5295..47c7ce6 100644 --- a/drivers/media/video/gspca/vc032x.c +++ b/drivers/media/video/gspca/vc032x.c @@ -1774,6 +1774,10 @@ static struct usb_driver sd_driver = { .id_table = device_table, .probe = sd_probe, .disconnect = gspca_disconnect, +#ifdef CONFIG_PM + .suspend = gspca_suspend, + .resume = gspca_resume, +#endif }; /* -- module insert / remove -- */ diff --git a/drivers/media/video/gspca/zc3xx.c b/drivers/media/video/gspca/zc3xx.c index d36f4d7..79436f2 100644 --- a/drivers/media/video/gspca/zc3xx.c +++ b/drivers/media/video/gspca/zc3xx.c @@ -7584,6 +7584,10 @@ static struct usb_driver sd_driver = { .id_table = device_table, .probe = sd_probe, .disconnect = gspca_disconnect, +#ifdef CONFIG_PM + .suspend = gspca_suspend, + .resume = gspca_resume, +#endif }; static int __init sd_mod_init(void) -- cgit v0.10.2 From f9b4a377dc6601a3299171c7b24c2c5189c0c10b Mon Sep 17 00:00:00 2001 From: Jean-Francois Moine Date: Wed, 3 Sep 2008 16:48:14 -0300 Subject: V4L/DVB (8719): gspca: Have VIDIOC_QUERYCTRL more compliant to the spec. - return -EINVAL when control not supported. - start the private controls at V4L2_CID_PRIVATE_BASE. Signed-off-by: Jean-Francois Moine Signed-off-by: Mauro Carvalho Chehab diff --git a/drivers/media/video/gspca/gspca.c b/drivers/media/video/gspca/gspca.c index 2f7bf26..061e191 100644 --- a/drivers/media/video/gspca/gspca.c +++ b/drivers/media/video/gspca/gspca.c @@ -884,11 +884,6 @@ static int vidioc_queryctrl(struct file *file, void *priv, return 0; } } - if (id >= V4L2_CID_BASE - && id <= V4L2_CID_LASTP1) { - q_ctrl->flags |= V4L2_CTRL_FLAG_DISABLED; - return 0; - } return -EINVAL; } diff --git a/drivers/media/video/gspca/t613.c b/drivers/media/video/gspca/t613.c index 357a2ed..962c1df 100644 --- a/drivers/media/video/gspca/t613.c +++ b/drivers/media/video/gspca/t613.c @@ -30,7 +30,7 @@ #define MAX_GAMMA 0x10 /* 0 to 15 */ -#define V4L2_CID_EFFECTS (V4L2_CID_PRIVATE_BASE + 3) +#define V4L2_CID_EFFECTS (V4L2_CID_PRIVATE_BASE + 0) MODULE_AUTHOR("Leandro Costantino "); MODULE_DESCRIPTION("GSPCA/T613 (JPEG Compliance) USB Camera Driver"); -- cgit v0.10.2 From 89a44b8a690ff2d8639b72931d9c197a8db0c803 Mon Sep 17 00:00:00 2001 From: Hans de Goede Date: Wed, 3 Sep 2008 16:48:16 -0300 Subject: V4L/DVB (8720): gspca: V4L2_CAP_SENSOR_UPSIDE_DOWN added as a cap for some webcams. This patch adds a V4L2_CAP_SENSOR_UPSIDE_DOWN flag to the capabilities flags, and sets this flag for the Philips SPC200NC cam (which has its sensor installed upside down). The same flag is also needed and added for the Philips SPC300NC. Together with a patch to libv4l which adds flipping the image in software this fixes the upside down display with the SPC200NC cam. Signed-of-by: Hans de Goede Signed-off-by: Jean-Francois Moine Signed-off-by: Mauro Carvalho Chehab diff --git a/drivers/media/video/gspca/gspca.c b/drivers/media/video/gspca/gspca.c index 061e191..3461bc9 100644 --- a/drivers/media/video/gspca/gspca.c +++ b/drivers/media/video/gspca/gspca.c @@ -851,6 +851,8 @@ static int vidioc_querycap(struct file *file, void *priv, cap->capabilities = V4L2_CAP_VIDEO_CAPTURE | V4L2_CAP_STREAMING | V4L2_CAP_READWRITE; + if (gspca_dev->flags & GSPCA_SENSOR_UPSIDE_DOWN_FLAG) + cap->capabilities |= V4L2_CAP_SENSOR_UPSIDE_DOWN; return 0; } diff --git a/drivers/media/video/gspca/gspca.h b/drivers/media/video/gspca/gspca.h index 2596568..1920c99 100644 --- a/drivers/media/video/gspca/gspca.h +++ b/drivers/media/video/gspca/gspca.h @@ -118,6 +118,9 @@ struct gspca_frame { struct v4l2_buffer v4l2_buf; }; +/* defines for the flags member */ +#define GSPCA_SENSOR_UPSIDE_DOWN_FLAG 0x01 + struct gspca_dev { struct video_device vdev; /* !! must be the first item */ struct file_operations fops; @@ -163,6 +166,7 @@ struct gspca_dev { char nurbs; /* number of allocated URBs */ char memory; /* memory type (V4L2_MEMORY_xxx) */ __u8 nbalt; /* number of USB alternate settings */ + __u8 flags; /* see GSPCA_XXX_FLAG defines */ }; int gspca_dev_probe(struct usb_interface *intf, diff --git a/drivers/media/video/gspca/zc3xx.c b/drivers/media/video/gspca/zc3xx.c index 79436f2..f1d8c7a 100644 --- a/drivers/media/video/gspca/zc3xx.c +++ b/drivers/media/video/gspca/zc3xx.c @@ -70,6 +70,10 @@ struct sd { unsigned short chip_revision; }; +#define DRIVER_INFO(sensor, flags) .driver_info = ((sensor) << 8) | (flags) +#define DRIVER_INFO_GET_SENSOR(driver_info) ((driver_info) >> 8) +#define DRIVER_INFO_GET_FLAGS(driver_info) ((driver_info) & 0xff) + /* V4L2 controls supported by the driver */ static int sd_setbrightness(struct gspca_dev *gspca_dev, __s32 val); static int sd_getbrightness(struct gspca_dev *gspca_dev, __s32 *val); @@ -7015,7 +7019,8 @@ static int sd_config(struct gspca_dev *gspca_dev, /* define some sensors from the vendor/product */ sd->sharpness = 2; - sd->sensor = id->driver_info; + sd->sensor = DRIVER_INFO_GET_SENSOR(id->driver_info); + gspca_dev->flags = DRIVER_INFO_GET_FLAGS(id->driver_info); sensor = zcxx_probeSensor(gspca_dev); if (sensor >= 0) PDEBUG(D_PROBE, "probe sensor -> %02x", sensor); @@ -7505,19 +7510,19 @@ static const __devinitdata struct usb_device_id device_table[] = { {USB_DEVICE(0x041e, 0x041e)}, #ifndef CONFIG_USB_ZC0301 {USB_DEVICE(0x041e, 0x4017)}, - {USB_DEVICE(0x041e, 0x401c), .driver_info = SENSOR_PAS106}, + {USB_DEVICE(0x041e, 0x401c), DRIVER_INFO(SENSOR_PAS106, 0)}, {USB_DEVICE(0x041e, 0x401e)}, {USB_DEVICE(0x041e, 0x401f)}, #endif {USB_DEVICE(0x041e, 0x4029)}, #ifndef CONFIG_USB_ZC0301 - {USB_DEVICE(0x041e, 0x4034), .driver_info = SENSOR_PAS106}, - {USB_DEVICE(0x041e, 0x4035), .driver_info = SENSOR_PAS106}, + {USB_DEVICE(0x041e, 0x4034), DRIVER_INFO(SENSOR_PAS106, 0)}, + {USB_DEVICE(0x041e, 0x4035), DRIVER_INFO(SENSOR_PAS106, 0)}, {USB_DEVICE(0x041e, 0x4036)}, {USB_DEVICE(0x041e, 0x403a)}, #endif - {USB_DEVICE(0x041e, 0x4051), .driver_info = SENSOR_TAS5130C_VF0250}, - {USB_DEVICE(0x041e, 0x4053), .driver_info = SENSOR_TAS5130C_VF0250}, + {USB_DEVICE(0x041e, 0x4051), DRIVER_INFO(SENSOR_TAS5130C_VF0250, 0)}, + {USB_DEVICE(0x041e, 0x4053), DRIVER_INFO(SENSOR_TAS5130C_VF0250, 0)}, #ifndef CONFIG_USB_ZC0301 {USB_DEVICE(0x0458, 0x7007)}, {USB_DEVICE(0x0458, 0x700c)}, @@ -7543,11 +7548,13 @@ static const __devinitdata struct usb_device_id device_table[] = { {USB_DEVICE(0x046d, 0x08d9)}, {USB_DEVICE(0x046d, 0x08d8)}, {USB_DEVICE(0x046d, 0x08da)}, - {USB_DEVICE(0x046d, 0x08dd), .driver_info = SENSOR_MC501CB}, - {USB_DEVICE(0x0471, 0x0325), .driver_info = SENSOR_PAS106}, - {USB_DEVICE(0x0471, 0x0326), .driver_info = SENSOR_PAS106}, - {USB_DEVICE(0x0471, 0x032d), .driver_info = SENSOR_PAS106}, - {USB_DEVICE(0x0471, 0x032e), .driver_info = SENSOR_PAS106}, + {USB_DEVICE(0x046d, 0x08dd), DRIVER_INFO(SENSOR_MC501CB, 0)}, + {USB_DEVICE(0x0471, 0x0325), DRIVER_INFO(SENSOR_PAS106, + GSPCA_SENSOR_UPSIDE_DOWN_FLAG)}, + {USB_DEVICE(0x0471, 0x0326), DRIVER_INFO(SENSOR_PAS106, + GSPCA_SENSOR_UPSIDE_DOWN_FLAG)}, + {USB_DEVICE(0x0471, 0x032d), DRIVER_INFO(SENSOR_PAS106, 0)}, + {USB_DEVICE(0x0471, 0x032e), DRIVER_INFO(SENSOR_PAS106, 0)}, {USB_DEVICE(0x055f, 0xc005)}, #ifndef CONFIG_USB_ZC0301 {USB_DEVICE(0x055f, 0xd003)}, @@ -7559,7 +7566,7 @@ static const __devinitdata struct usb_device_id device_table[] = { {USB_DEVICE(0x0ac8, 0x301b)}, {USB_DEVICE(0x0ac8, 0x303b)}, #endif - {USB_DEVICE(0x0ac8, 0x305b), .driver_info = SENSOR_TAS5130C_VF0250}, + {USB_DEVICE(0x0ac8, 0x305b), DRIVER_INFO(SENSOR_TAS5130C_VF0250, 0)}, #ifndef CONFIG_USB_ZC0301 {USB_DEVICE(0x0ac8, 0x307b)}, {USB_DEVICE(0x10fd, 0x0128)}, diff --git a/include/linux/videodev2.h b/include/linux/videodev2.h index 6c73516..4c30655 100644 --- a/include/linux/videodev2.h +++ b/include/linux/videodev2.h @@ -261,6 +261,11 @@ struct v4l2_capability { #define V4L2_CAP_ASYNCIO 0x02000000 /* async I/O */ #define V4L2_CAP_STREAMING 0x04000000 /* streaming I/O ioctls */ +/* This flags gets set if the "sensor" is known to be upside down and this can + *not* be fixed using v4l2 flipx/y controls. Note that absence of this flag + is not a guarantee for the image not being upside down. */ +#define V4L2_CAP_SENSOR_UPSIDE_DOWN 0x10000000 + /* * V I D E O I M A G E F O R M A T */ -- cgit v0.10.2 From 09a29b771535e0b8cef66946fdaeb43b0e545570 Mon Sep 17 00:00:00 2001 From: Michael Krufky Date: Wed, 3 Sep 2008 16:48:17 -0300 Subject: V4L/DVB (8722): sms1xxx: fix typo in license header This should have read, "GNU General Public License version 2" rather than, "GNU General Public License version 3" This was actually a typo mass-blunder -- this is not a change in licence, as the code was always GPLv2. Signed-off-by: Uri Shkolnik Signed-off-by: Michael Krufky Signed-off-by: Mauro Carvalho Chehab diff --git a/drivers/media/dvb/siano/sms-cards.c b/drivers/media/dvb/siano/sms-cards.c index e7a8ac0..cc5efb6 100644 --- a/drivers/media/dvb/siano/sms-cards.c +++ b/drivers/media/dvb/siano/sms-cards.c @@ -4,7 +4,7 @@ * Copyright (c) 2008 Michael Krufky * * This program is free software; you can redistribute it and/or modify - * it under the terms of the GNU General Public License version 3 as + * it under the terms of the GNU General Public License version 2 as * published by the Free Software Foundation; * * Software distributed under the License is distributed on an "AS IS" diff --git a/drivers/media/dvb/siano/sms-cards.h b/drivers/media/dvb/siano/sms-cards.h index 83b39bc..c8f3da6 100644 --- a/drivers/media/dvb/siano/sms-cards.h +++ b/drivers/media/dvb/siano/sms-cards.h @@ -4,7 +4,7 @@ * Copyright (c) 2008 Michael Krufky * * This program is free software; you can redistribute it and/or modify - * it under the terms of the GNU General Public License version 3 as + * it under the terms of the GNU General Public License version 2 as * published by the Free Software Foundation; * * Software distributed under the License is distributed on an "AS IS" diff --git a/drivers/media/dvb/siano/smscoreapi.c b/drivers/media/dvb/siano/smscoreapi.c index c5f45fe..6576fbb 100644 --- a/drivers/media/dvb/siano/smscoreapi.c +++ b/drivers/media/dvb/siano/smscoreapi.c @@ -8,7 +8,7 @@ * Copyright (c), 2005-2008 Siano Mobile Silicon, Inc. * * This program is free software; you can redistribute it and/or modify - * it under the terms of the GNU General Public License version 3 as + * it under the terms of the GNU General Public License version 2 as * published by the Free Software Foundation; * * Software distributed under the License is distributed on an "AS IS" diff --git a/drivers/media/dvb/siano/smscoreapi.h b/drivers/media/dvb/siano/smscoreapi.h index c1f8f1d..8d973f7 100644 --- a/drivers/media/dvb/siano/smscoreapi.h +++ b/drivers/media/dvb/siano/smscoreapi.h @@ -6,7 +6,7 @@ * Copyright (c), 2005-2008 Siano Mobile Silicon, Inc. * * This program is free software; you can redistribute it and/or modify - * it under the terms of the GNU General Public License version 3 as + * it under the terms of the GNU General Public License version 2 as * published by the Free Software Foundation; * * Software distributed under the License is distributed on an "AS IS" diff --git a/drivers/media/dvb/siano/smsdvb.c b/drivers/media/dvb/siano/smsdvb.c index 229274a..8d490e1 100644 --- a/drivers/media/dvb/siano/smsdvb.c +++ b/drivers/media/dvb/siano/smsdvb.c @@ -6,7 +6,7 @@ * Copyright (c), 2005-2008 Siano Mobile Silicon, Inc. * * This program is free software; you can redistribute it and/or modify - * it under the terms of the GNU General Public License version 3 as + * it under the terms of the GNU General Public License version 2 as * published by the Free Software Foundation; * * Software distributed under the License is distributed on an "AS IS" diff --git a/drivers/media/dvb/siano/smsusb.c b/drivers/media/dvb/siano/smsusb.c index c10b184..87a3c24 100644 --- a/drivers/media/dvb/siano/smsusb.c +++ b/drivers/media/dvb/siano/smsusb.c @@ -6,7 +6,7 @@ * Copyright (c), 2005-2008 Siano Mobile Silicon, Inc. * * This program is free software; you can redistribute it and/or modify - * it under the terms of the GNU General Public License version 3 as + * it under the terms of the GNU General Public License version 2 as * published by the Free Software Foundation; * * Software distributed under the License is distributed on an "AS IS" -- cgit v0.10.2 From f46466e7d6ff4871e5faae32d277175293a34c1f Mon Sep 17 00:00:00 2001 From: Simon Arlott Date: Wed, 3 Sep 2008 16:48:20 -0300 Subject: V4L/DVB (8726): link tuner before saa7134 If saa7134_init is run before v4l2_i2c_drv_init (tuner), then saa7134_board_init2 will try to set the tuner type for devices that don't exist yet. This moves tuner to before all of the device-specific drivers so that it's loaded early enough on boot. Signed-off-by: Simon Arlott Signed-off-by: Andrew Morton Signed-off-by: Mauro Carvalho Chehab diff --git a/drivers/media/video/Makefile b/drivers/media/video/Makefile index bbc6f8b..ef7c8d3 100644 --- a/drivers/media/video/Makefile +++ b/drivers/media/video/Makefile @@ -20,6 +20,8 @@ ifeq ($(CONFIG_VIDEO_V4L1_COMPAT),y) obj-$(CONFIG_VIDEO_DEV) += v4l1-compat.o endif +obj-$(CONFIG_VIDEO_TUNER) += tuner.o + obj-$(CONFIG_VIDEO_BT848) += bt8xx/ obj-$(CONFIG_VIDEO_IR_I2C) += ir-kbd-i2c.o obj-$(CONFIG_VIDEO_TVAUDIO) += tvaudio.o @@ -85,8 +87,6 @@ obj-$(CONFIG_VIDEO_HEXIUM_GEMINI) += hexium_gemini.o obj-$(CONFIG_VIDEO_DPC) += dpc7146.o obj-$(CONFIG_TUNER_3036) += tuner-3036.o -obj-$(CONFIG_VIDEO_TUNER) += tuner.o - obj-$(CONFIG_VIDEOBUF_GEN) += videobuf-core.o obj-$(CONFIG_VIDEOBUF_DMA_SG) += videobuf-dma-sg.o obj-$(CONFIG_VIDEOBUF_DMA_CONTIG) += videobuf-dma-contig.o -- cgit v0.10.2 From b54ff9398ac7d38a129167b580383943592b6f08 Mon Sep 17 00:00:00 2001 From: Rene Herman Date: Wed, 3 Sep 2008 16:48:21 -0300 Subject: V4L/DVB (8727): V4L1: make PMS not autoprobe when builtin. The old Mediavision Pro Movie Studio legacy ISA V4L1 driver was found to hang the boot during Ingo Molnar's testing of randconfig kernels. Have it require a "pms.enable=1" kernel parameter to enable the driver when builtin which avoids such problems. This is a deprecated and, very likely, unused driver. Nothing changes modular behaviour moreover. Signed-off-by: Rene Herman Acked-by: Alan Cox Signed-off-by: Andrew Morton Signed-off-by: Mauro Carvalho Chehab diff --git a/drivers/media/video/pms.c b/drivers/media/video/pms.c index 00425d7..ede522a 100644 --- a/drivers/media/video/pms.c +++ b/drivers/media/video/pms.c @@ -1019,10 +1019,22 @@ static int init_mediavision(void) * Initialization and module stuff */ +#ifndef MODULE +static int enable; +module_param(enable, int, 0); +#endif + static int __init init_pms_cards(void) { printk(KERN_INFO "Mediavision Pro Movie Studio driver 0.02\n"); +#ifndef MODULE + if (!enable) { + printk(KERN_INFO "Not enabled\n"); + return -ENODEV; + } +#endif + data_port = io_port +1; if(init_mediavision()) -- cgit v0.10.2 From 4ce0b659689a97bc356e96aeac813cad2d137339 Mon Sep 17 00:00:00 2001 From: Rene Herman Date: Wed, 3 Sep 2008 16:48:23 -0300 Subject: V4L/DVB (8728): 1-make-pms-not-autoprobe-when-builtin update On 10-08-08 23:37, Alan Cox wrote: > > Would probably make the printk "pms: not enabled, use pms.enable=1 to > probe" > > So you know > a) What is wittering about not being probed > b) How to undo it. > > But thats trivia really. Signed-off-by: Rene Herman Signed-off-by: Andrew Morton Signed-off-by: Mauro Carvalho Chehab diff --git a/drivers/media/video/pms.c b/drivers/media/video/pms.c index ede522a..7c84f79 100644 --- a/drivers/media/video/pms.c +++ b/drivers/media/video/pms.c @@ -1030,7 +1030,8 @@ static int __init init_pms_cards(void) #ifndef MODULE if (!enable) { - printk(KERN_INFO "Not enabled\n"); + printk(KERN_INFO "PMS: not enabled, use pms.enable=1 to " + "probe\n"); return -ENODEV; } #endif -- cgit v0.10.2 From 5b5aff83a549c8f1e425e06d46ec951eae950b37 Mon Sep 17 00:00:00 2001 From: Mauro Carvalho Chehab Date: Wed, 3 Sep 2008 17:11:52 -0300 Subject: V4L/DVB (8749): Fix error code, when camera is not turned on by sonypi Signed-off-by: Mauro Carvalho Chehab diff --git a/drivers/media/video/meye.c b/drivers/media/video/meye.c index 7c8ef6a..a9ef780 100644 --- a/drivers/media/video/meye.c +++ b/drivers/media/video/meye.c @@ -1806,6 +1806,7 @@ static int __devinit meye_probe(struct pci_dev *pcidev, memcpy(meye.video_dev, &meye_template, sizeof(meye_template)); meye.video_dev->parent = &meye.mchip_dev->dev; + ret = -EIO; if ((ret = sony_pic_camera_command(SONY_PIC_COMMAND_SETCAMERA, 1))) { printk(KERN_ERR "meye: unable to power on the camera\n"); printk(KERN_ERR "meye: did you enable the camera in " @@ -1813,7 +1814,6 @@ static int __devinit meye_probe(struct pci_dev *pcidev, goto outsonypienable; } - ret = -EIO; if ((ret = pci_enable_device(meye.mchip_dev))) { printk(KERN_ERR "meye: pci_enable_device failed\n"); goto outenabledev; -- cgit v0.10.2 From f3b9f50ef771670b5d94c568241d6766691c6c18 Mon Sep 17 00:00:00 2001 From: Henrik Kretzschmar Date: Wed, 3 Sep 2008 17:11:53 -0300 Subject: V4L/DVB (8750): V4L: check inval in video_register_device_index() Better check the video_device pointer before using it. Signed-off-by: Henrik Kretzschmar Signed-off-by: Mauro Carvalho Chehab diff --git a/drivers/media/video/v4l2-dev.c b/drivers/media/video/v4l2-dev.c index 0320fb8..155fdec 100644 --- a/drivers/media/video/v4l2-dev.c +++ b/drivers/media/video/v4l2-dev.c @@ -257,6 +257,9 @@ int video_register_device_index(struct video_device *vfd, int type, int nr, int ret; char *name_base; + if (vfd == NULL) + return -EINVAL; + switch (type) { case VFL_TYPE_GRABBER: base = MINOR_VFL_TYPE_GRABBER_MIN; -- cgit v0.10.2 From 980d4f17345fe420fda2a84cd4a28d5d41d73cef Mon Sep 17 00:00:00 2001 From: Mauro Carvalho Chehab Date: Wed, 3 Sep 2008 17:11:53 -0300 Subject: V4L/DVB (8751): vivi: Fix some issues at vivi register routine This patch fixes several small issues at vivi register routines: 1) minor and n_devs should be unsigned; 2) n_devs = 0 were not properly handled; 3) if n_devs specify a high number, the driver would just roll back and won't register any device. The proper behaviour is to keep all succeded devices registered; 4) both n_devs and minor were using 0 as permissions. Better to have them with 0444. With the current patch, if n_devs specify a very large value, it will register all possible devices. For example, on a machine without any other V4L drivers loaded, with this patch, we will have something like: vivi: V4L2 device registered as /dev/video0 vivi: V4L2 device registered as /dev/video1 vivi: V4L2 device registered as /dev/video2 ... vivi: V4L2 device registered as /dev/video31 video_register_device_index: get_index failed Video Technology Magazine Virtual Video Capture Board ver 0.5.0 successfully loaded. 5) The number of allocated devices on success is now kept at n_devs: $ cat /sys/module/vivi/parameters/n_devs 32 Thanks to Henne for pointing that there were some issues at vivi. Cc: Henne Signed-off-by: Mauro Carvalho Chehab diff --git a/drivers/media/video/vivi.c b/drivers/media/video/vivi.c index 3518af0..f55d77d 100644 --- a/drivers/media/video/vivi.c +++ b/drivers/media/video/vivi.c @@ -1104,19 +1104,29 @@ static struct video_device vivi_template = { Initialization and module stuff ------------------------------------------------------------------*/ +/* This routine allocates from 1 to n_devs virtual drivers. + + The real maximum number of virtual drivers will depend on how many drivers + will succeed. This is limited to the maximum number of devices that + videodev supports. Since there are 64 minors for video grabbers, this is + currently the theoretical maximum limit. However, a further limit does + exist at videodev that forbids any driver to register more than 32 video + grabbers. + */ static int __init vivi_init(void) { int ret = -ENOMEM, i; struct vivi_dev *dev; struct video_device *vfd; + if (n_devs <= 0) + n_devs = 1; + for (i = 0; i < n_devs; i++) { dev = kzalloc(sizeof(*dev), GFP_KERNEL); - if (NULL == dev) + if (!dev) break; - list_add_tail(&dev->vivi_devlist, &vivi_devlist); - /* init video dma queues */ INIT_LIST_HEAD(&dev->vidq.active); init_waitqueue_head(&dev->vidq.wq); @@ -1126,14 +1136,27 @@ static int __init vivi_init(void) mutex_init(&dev->mutex); vfd = video_device_alloc(); - if (NULL == vfd) + if (!vfd) { + kfree(dev); break; + } *vfd = vivi_template; ret = video_register_device(vfd, VFL_TYPE_GRABBER, video_nr); - if (ret < 0) + if (ret < 0) { + video_device_release(vfd); + kfree(dev); + + /* If some registers succeeded, keep driver */ + if (i) + ret = 0; + break; + } + + /* Now that everything is fine, let's add it to device list */ + list_add_tail(&dev->vivi_devlist, &vivi_devlist); snprintf(vfd->name, sizeof(vfd->name), "%s (%i)", vivi_template.name, vfd->minor); @@ -1149,11 +1172,16 @@ static int __init vivi_init(void) if (ret < 0) { vivi_release(); printk(KERN_INFO "Error %d while loading vivi driver\n", ret); - } else + } else { printk(KERN_INFO "Video Technology Magazine Virtual Video " "Capture Board ver %u.%u.%u successfully loaded.\n", (VIVI_VERSION >> 16) & 0xFF, (VIVI_VERSION >> 8) & 0xFF, VIVI_VERSION & 0xFF); + + /* n_devs will reflect the actual number of allocated devices */ + n_devs = i; + } + return ret; } @@ -1169,10 +1197,10 @@ MODULE_DESCRIPTION("Video Technology Magazine Virtual Video Capture Board"); MODULE_AUTHOR("Mauro Carvalho Chehab, Ted Walther and John Sokol"); MODULE_LICENSE("Dual BSD/GPL"); -module_param(video_nr, int, 0); +module_param(video_nr, uint, 0444); MODULE_PARM_DESC(video_nr, "video iminor start number"); -module_param(n_devs, int, 0); +module_param(n_devs, uint, 0444); MODULE_PARM_DESC(n_devs, "number of video devices to create"); module_param_named(debug, vivi_template.debug, int, 0444); -- cgit v0.10.2 From c6eb8eafdba4ad18b4520a0d28a38bc9e61883ea Mon Sep 17 00:00:00 2001 From: Hans Verkuil Date: Wed, 3 Sep 2008 17:11:54 -0300 Subject: V4L/DVB (8757): v4l-dvb: fix a bunch of sparse warnings Fixed a lot of sparse warnings: mostly warnings about shadowed variables and signed/unsigned mismatches. Signed-off-by: Hans Verkuil Signed-off-by: Mauro Carvalho Chehab diff --git a/drivers/media/common/saa7146_video.c b/drivers/media/common/saa7146_video.c index e8bc7ab..99be9e5 100644 --- a/drivers/media/common/saa7146_video.c +++ b/drivers/media/common/saa7146_video.c @@ -1068,7 +1068,7 @@ int saa7146_video_do_ioctl(struct inode *inode, struct file *file, unsigned int { v4l2_std_id *id = arg; int found = 0; - int i, err; + int i; DEB_EE(("VIDIOC_S_STD\n")); @@ -1116,7 +1116,6 @@ int saa7146_video_do_ioctl(struct inode *inode, struct file *file, unsigned int case VIDIOC_OVERLAY: { int on = *(int *)arg; - int err = 0; DEB_D(("VIDIOC_OVERLAY on:%d\n",on)); if (on != 0) { @@ -1192,7 +1191,6 @@ int saa7146_video_do_ioctl(struct inode *inode, struct file *file, unsigned int case VIDIOCGMBUF: { struct video_mbuf *mbuf = arg; - struct videobuf_queue *q; int i; /* fixme: number of capture buffers and sizes for v4l apps */ diff --git a/drivers/media/common/tuners/tuner-simple.c b/drivers/media/common/tuners/tuner-simple.c index 597e47f..aa773a6 100644 --- a/drivers/media/common/tuners/tuner-simple.c +++ b/drivers/media/common/tuners/tuner-simple.c @@ -253,7 +253,7 @@ static struct tuner_params *simple_tuner_params(struct dvb_frontend *fe, static int simple_config_lookup(struct dvb_frontend *fe, struct tuner_params *t_params, - int *frequency, u8 *config, u8 *cb) + unsigned *frequency, u8 *config, u8 *cb) { struct tuner_simple_priv *priv = fe->tuner_priv; int i; @@ -587,45 +587,45 @@ static int simple_set_tv_freq(struct dvb_frontend *fe, priv->last_div = div; if (t_params->has_tda9887) { struct v4l2_priv_tun_config tda9887_cfg; - int config = 0; + int tda_config = 0; int is_secam_l = (params->std & (V4L2_STD_SECAM_L | V4L2_STD_SECAM_LC)) && !(params->std & ~(V4L2_STD_SECAM_L | V4L2_STD_SECAM_LC)); tda9887_cfg.tuner = TUNER_TDA9887; - tda9887_cfg.priv = &config; + tda9887_cfg.priv = &tda_config; if (params->std == V4L2_STD_SECAM_LC) { if (t_params->port1_active ^ t_params->port1_invert_for_secam_lc) - config |= TDA9887_PORT1_ACTIVE; + tda_config |= TDA9887_PORT1_ACTIVE; if (t_params->port2_active ^ t_params->port2_invert_for_secam_lc) - config |= TDA9887_PORT2_ACTIVE; + tda_config |= TDA9887_PORT2_ACTIVE; } else { if (t_params->port1_active) - config |= TDA9887_PORT1_ACTIVE; + tda_config |= TDA9887_PORT1_ACTIVE; if (t_params->port2_active) - config |= TDA9887_PORT2_ACTIVE; + tda_config |= TDA9887_PORT2_ACTIVE; } if (t_params->intercarrier_mode) - config |= TDA9887_INTERCARRIER; + tda_config |= TDA9887_INTERCARRIER; if (is_secam_l) { if (i == 0 && t_params->default_top_secam_low) - config |= TDA9887_TOP(t_params->default_top_secam_low); + tda_config |= TDA9887_TOP(t_params->default_top_secam_low); else if (i == 1 && t_params->default_top_secam_mid) - config |= TDA9887_TOP(t_params->default_top_secam_mid); + tda_config |= TDA9887_TOP(t_params->default_top_secam_mid); else if (t_params->default_top_secam_high) - config |= TDA9887_TOP(t_params->default_top_secam_high); + tda_config |= TDA9887_TOP(t_params->default_top_secam_high); } else { if (i == 0 && t_params->default_top_low) - config |= TDA9887_TOP(t_params->default_top_low); + tda_config |= TDA9887_TOP(t_params->default_top_low); else if (i == 1 && t_params->default_top_mid) - config |= TDA9887_TOP(t_params->default_top_mid); + tda_config |= TDA9887_TOP(t_params->default_top_mid); else if (t_params->default_top_high) - config |= TDA9887_TOP(t_params->default_top_high); + tda_config |= TDA9887_TOP(t_params->default_top_high); } if (t_params->default_pll_gating_18) - config |= TDA9887_GATING_18; + tda_config |= TDA9887_GATING_18; i2c_clients_command(priv->i2c_props.adap, TUNER_SET_CONFIG, &tda9887_cfg); } @@ -813,7 +813,8 @@ static u32 simple_dvb_configure(struct dvb_frontend *fe, u8 *buf, static struct tuner_params *t_params; u8 config, cb; u32 div; - int ret, frequency = params->frequency / 62500; + int ret; + unsigned frequency = params->frequency / 62500; t_params = simple_tuner_params(fe, TUNER_PARAM_TYPE_DIGITAL); ret = simple_config_lookup(fe, t_params, &frequency, &config, &cb); diff --git a/drivers/media/dvb/dvb-core/dmxdev.c b/drivers/media/dvb/dvb-core/dmxdev.c index 1cf9fcb..069d847 100644 --- a/drivers/media/dvb/dvb-core/dmxdev.c +++ b/drivers/media/dvb/dvb-core/dmxdev.c @@ -641,7 +641,6 @@ static int dvb_dmxdev_filter_start(struct dmxdev_filter *filter) struct timespec timeout = { 0 }; struct dmx_pes_filter_params *para = &filter->params.pes; dmx_output_t otype; - int ret; int ts_type; enum dmx_ts_pes ts_pes; struct dmx_ts_feed **tsfeed = &filter->feed.ts; diff --git a/drivers/media/dvb/dvb-core/dvb_ca_en50221.c b/drivers/media/dvb/dvb-core/dvb_ca_en50221.c index 8e5dd7b..98ee167 100644 --- a/drivers/media/dvb/dvb-core/dvb_ca_en50221.c +++ b/drivers/media/dvb/dvb-core/dvb_ca_en50221.c @@ -1032,7 +1032,7 @@ static int dvb_ca_en50221_thread(void *data) /* we need this extra check for annoying interfaces like the budget-av */ if ((!(ca->flags & DVB_CA_EN50221_FLAG_IRQ_CAMCHANGE)) && (ca->pub->poll_slot_status)) { - int status = ca->pub->poll_slot_status(ca->pub, slot, 0); + status = ca->pub->poll_slot_status(ca->pub, slot, 0); if (!(status & DVB_CA_EN50221_POLL_CAM_PRESENT)) { ca->slot_info[slot].slot_state = DVB_CA_SLOTSTATE_NONE; dvb_ca_en50221_thread_update_delay(ca); @@ -1089,7 +1089,7 @@ static int dvb_ca_en50221_thread(void *data) /* we need this extra check for annoying interfaces like the budget-av */ if ((!(ca->flags & DVB_CA_EN50221_FLAG_IRQ_CAMCHANGE)) && (ca->pub->poll_slot_status)) { - int status = ca->pub->poll_slot_status(ca->pub, slot, 0); + status = ca->pub->poll_slot_status(ca->pub, slot, 0); if (!(status & DVB_CA_EN50221_POLL_CAM_PRESENT)) { ca->slot_info[slot].slot_state = DVB_CA_SLOTSTATE_NONE; dvb_ca_en50221_thread_update_delay(ca); diff --git a/drivers/media/dvb/dvb-core/dvb_frontend.c b/drivers/media/dvb/dvb-core/dvb_frontend.c index 8cbdb21..3526e3e 100644 --- a/drivers/media/dvb/dvb-core/dvb_frontend.c +++ b/drivers/media/dvb/dvb-core/dvb_frontend.c @@ -889,13 +889,13 @@ static int dvb_frontend_ioctl(struct inode *inode, struct file *file, * initialization, so parg is 8 bits and does not * include the initialization or start bit */ - unsigned long cmd = ((unsigned long) parg) << 1; + unsigned long swcmd = ((unsigned long) parg) << 1; struct timeval nexttime; struct timeval tv[10]; int i; u8 last = 1; if (dvb_frontend_debug) - printk("%s switch command: 0x%04lx\n", __func__, cmd); + printk("%s switch command: 0x%04lx\n", __func__, swcmd); do_gettimeofday(&nexttime); if (dvb_frontend_debug) memcpy(&tv[0], &nexttime, sizeof(struct timeval)); @@ -908,12 +908,12 @@ static int dvb_frontend_ioctl(struct inode *inode, struct file *file, for (i = 0; i < 9; i++) { if (dvb_frontend_debug) do_gettimeofday(&tv[i + 1]); - if ((cmd & 0x01) != last) { + if ((swcmd & 0x01) != last) { /* set voltage to (last ? 13V : 18V) */ fe->ops.set_voltage(fe, (last) ? SEC_VOLTAGE_13 : SEC_VOLTAGE_18); last = (last) ? 0 : 1; } - cmd = cmd >> 1; + swcmd = swcmd >> 1; if (i != 8) dvb_frontend_sleep_until(&nexttime, 8000); } diff --git a/drivers/media/dvb/dvb-usb/cxusb.c b/drivers/media/dvb/dvb-usb/cxusb.c index aaa0b6f..5634002 100644 --- a/drivers/media/dvb/dvb-usb/cxusb.c +++ b/drivers/media/dvb/dvb-usb/cxusb.c @@ -210,7 +210,7 @@ static int cxusb_aver_power_ctrl(struct dvb_usb_device *d, int onoff) if (d->state == DVB_USB_STATE_INIT && usb_set_interface(d->udev, 0, 0) < 0) err("set interface failed"); - do; while (!(ret = cxusb_ctrl_msg(d, CMD_POWER_ON, NULL, 0, NULL, 0)) && + do {} while (!(ret = cxusb_ctrl_msg(d, CMD_POWER_ON, NULL, 0, NULL, 0)) && !(ret = cxusb_ctrl_msg(d, 0x15, NULL, 0, NULL, 0)) && !(ret = cxusb_ctrl_msg(d, 0x17, NULL, 0, NULL, 0)) && 0); if (!ret) { diff --git a/drivers/media/radio/radio-maxiradio.c b/drivers/media/radio/radio-maxiradio.c index 43c7549..e210da1 100644 --- a/drivers/media/radio/radio-maxiradio.c +++ b/drivers/media/radio/radio-maxiradio.c @@ -156,28 +156,28 @@ static void set_freq(__u16 io, __u32 freq) { unsigned long int si; int bl; - int data = FREQ2BITS(freq); + int val = FREQ2BITS(freq); /* TEA5757 shift register bits (see pdf) */ - outbit(0,io); // 24 search - outbit(1,io); // 23 search up/down + outbit(0, io); /* 24 search */ + outbit(1, io); /* 23 search up/down */ - outbit(0,io); // 22 stereo/mono + outbit(0, io); /* 22 stereo/mono */ - outbit(0,io); // 21 band - outbit(0,io); // 20 band (only 00=FM works I think) + outbit(0, io); /* 21 band */ + outbit(0, io); /* 20 band (only 00=FM works I think) */ - outbit(0,io); // 19 port ? - outbit(0,io); // 18 port ? + outbit(0, io); /* 19 port ? */ + outbit(0, io); /* 18 port ? */ - outbit(0,io); // 17 search level - outbit(0,io); // 16 search level + outbit(0, io); /* 17 search level */ + outbit(0, io); /* 16 search level */ si = 0x8000; - for (bl = 1; bl <= 16 ; bl++) { - outbit(data & si,io); - si >>=1; + for (bl = 1; bl <= 16; bl++) { + outbit(val & si, io); + si >>= 1; } dprintk(1, "Radio freq set to %d.%02d MHz\n", diff --git a/drivers/media/video/bt8xx/bttv-cards.c b/drivers/media/video/bt8xx/bttv-cards.c index 1c56ae9..9001de2 100644 --- a/drivers/media/video/bt8xx/bttv-cards.c +++ b/drivers/media/video/bt8xx/bttv-cards.c @@ -3144,8 +3144,9 @@ static void identify_by_eeprom(struct bttv *btv, unsigned char eeprom_data[256]) static void flyvideo_gpio(struct bttv *btv) { - int gpio,has_remote,has_radio,is_capture_only,is_lr90,has_tda9820_tda9821; - int tuner=UNSET,ttype; + int gpio, has_remote, has_radio, is_capture_only; + int is_lr90, has_tda9820_tda9821; + int tuner_type = UNSET, ttype; gpio_inout(0xffffff, 0); udelay(8); /* without this we would see the 0x1800 mask */ @@ -3163,20 +3164,26 @@ static void flyvideo_gpio(struct bttv *btv) * xxxF00(LR26/LR50), xxxFE0(LR90): Remote control chip (LVA001 or CF45) soldered * Note: Some bits are Audio_Mask ! */ - ttype=(gpio&0x0f0000)>>16; - switch(ttype) { - case 0x0: tuner=2; /* NTSC, e.g. TPI8NSR11P */ + ttype = (gpio & 0x0f0000) >> 16; + switch (ttype) { + case 0x0: + tuner_type = 2; /* NTSC, e.g. TPI8NSR11P */ break; - case 0x2: tuner=39;/* LG NTSC (newer TAPC series) TAPC-H701P */ + case 0x2: + tuner_type = 39; /* LG NTSC (newer TAPC series) TAPC-H701P */ break; - case 0x4: tuner=5; /* Philips PAL TPI8PSB02P, TPI8PSB12P, TPI8PSB12D or FI1216, FM1216 */ + case 0x4: + tuner_type = 5; /* Philips PAL TPI8PSB02P, TPI8PSB12P, TPI8PSB12D or FI1216, FM1216 */ break; - case 0x6: tuner=37;/* LG PAL (newer TAPC series) TAPC-G702P */ + case 0x6: + tuner_type = 37; /* LG PAL (newer TAPC series) TAPC-G702P */ break; - case 0xC: tuner=3; /* Philips SECAM(+PAL) FQ1216ME or FI1216MF */ + case 0xC: + tuner_type = 3; /* Philips SECAM(+PAL) FQ1216ME or FI1216MF */ break; default: printk(KERN_INFO "bttv%d: FlyVideo_gpio: unknown tuner type.\n", btv->c.nr); + break; } has_remote = gpio & 0x800000; @@ -3189,23 +3196,26 @@ static void flyvideo_gpio(struct bttv *btv) /* * gpio & 0x001000 output bit for audio routing */ - if(is_capture_only) - tuner = TUNER_ABSENT; /* No tuner present */ + if (is_capture_only) + tuner_type = TUNER_ABSENT; /* No tuner present */ printk(KERN_INFO "bttv%d: FlyVideo Radio=%s RemoteControl=%s Tuner=%d gpio=0x%06x\n", - btv->c.nr, has_radio? "yes":"no ", has_remote? "yes":"no ", tuner, gpio); + btv->c.nr, has_radio ? "yes" : "no ", + has_remote ? "yes" : "no ", tuner_type, gpio); printk(KERN_INFO "bttv%d: FlyVideo LR90=%s tda9821/tda9820=%s capture_only=%s\n", - btv->c.nr, is_lr90?"yes":"no ", has_tda9820_tda9821?"yes":"no ", - is_capture_only?"yes":"no "); + btv->c.nr, is_lr90 ? "yes" : "no ", + has_tda9820_tda9821 ? "yes" : "no ", + is_capture_only ? "yes" : "no "); - if (tuner != UNSET) /* only set if known tuner autodetected, else let insmod option through */ - btv->tuner_type = tuner; + if (tuner_type != UNSET) /* only set if known tuner autodetected, else let insmod option through */ + btv->tuner_type = tuner_type; btv->has_radio = has_radio; /* LR90 Audio Routing is done by 2 hef4052, so Audio_Mask has 4 bits: 0x001c80 * LR26/LR50 only has 1 hef4052, Audio_Mask 0x000c00 * Audio options: from tuner, from tda9821/tda9821(mono,stereo,sap), from tda9874, ext., mute */ - if(has_tda9820_tda9821) btv->audio_mode_gpio = lt9415_audio; + if (has_tda9820_tda9821) + btv->audio_mode_gpio = lt9415_audio; /* todo: if(has_tda9874) btv->audio_mode_gpio = fv2000s_audio; */ } @@ -3962,7 +3972,7 @@ static int tuner_1_table[] = { static void __devinit avermedia_eeprom(struct bttv *btv) { - int tuner_make,tuner_tv_fm,tuner_format,tuner=0; + int tuner_make, tuner_tv_fm, tuner_format, tuner_type = 0; tuner_make = (eeprom_data[0x41] & 0x7); tuner_tv_fm = (eeprom_data[0x41] & 0x18) >> 3; @@ -3970,24 +3980,24 @@ static void __devinit avermedia_eeprom(struct bttv *btv) btv->has_remote = (eeprom_data[0x42] & 0x01); if (tuner_make == 0 || tuner_make == 2) - if(tuner_format <=0x0a) - tuner = tuner_0_table[tuner_format]; + if (tuner_format <= 0x0a) + tuner_type = tuner_0_table[tuner_format]; if (tuner_make == 1) - if(tuner_format <=9) - tuner = tuner_1_table[tuner_format]; + if (tuner_format <= 9) + tuner_type = tuner_1_table[tuner_format]; if (tuner_make == 4) - if(tuner_format == 0x09) - tuner = TUNER_LG_NTSC_NEW_TAPC; /* TAPC-G702P */ + if (tuner_format == 0x09) + tuner_type = TUNER_LG_NTSC_NEW_TAPC; /* TAPC-G702P */ printk(KERN_INFO "bttv%d: Avermedia eeprom[0x%02x%02x]: tuner=", - btv->c.nr,eeprom_data[0x41],eeprom_data[0x42]); - if(tuner) { - btv->tuner_type=tuner; - printk("%d",tuner); + btv->c.nr, eeprom_data[0x41], eeprom_data[0x42]); + if (tuner_type) { + btv->tuner_type = tuner_type; + printk(KERN_CONT "%d", tuner_type); } else - printk("Unknown type"); - printk(" radio:%s remote control:%s\n", + printk(KERN_CONT "Unknown type"); + printk(KERN_CONT " radio:%s remote control:%s\n", tuner_tv_fm ? "yes" : "no", btv->has_remote ? "yes" : "no"); } diff --git a/drivers/media/video/bt8xx/bttv-driver.c b/drivers/media/video/bt8xx/bttv-driver.c index 85bf31a..6ae4cc8 100644 --- a/drivers/media/video/bt8xx/bttv-driver.c +++ b/drivers/media/video/bt8xx/bttv-driver.c @@ -96,7 +96,6 @@ static unsigned int irq_iswitch; static unsigned int uv_ratio = 50; static unsigned int full_luma_range; static unsigned int coring; -extern int no_overlay; /* API features (turn on/off stuff for testing) */ static unsigned int v4l2 = 1; diff --git a/drivers/media/video/bt8xx/bttv-risc.c b/drivers/media/video/bt8xx/bttv-risc.c index 649682a..5b1b8e4 100644 --- a/drivers/media/video/bt8xx/bttv-risc.c +++ b/drivers/media/video/bt8xx/bttv-risc.c @@ -244,7 +244,8 @@ bttv_risc_overlay(struct bttv *btv, struct btcx_riscmem *risc, const struct bttv_format *fmt, struct bttv_overlay *ov, int skip_even, int skip_odd) { - int dwords,rc,line,maxy,start,end,skip,nskips; + int dwords, rc, line, maxy, start, end; + unsigned skip, nskips; struct btcx_skiplist *skips; __le32 *rp; u32 ri,ra; diff --git a/drivers/media/video/bt8xx/bttvp.h b/drivers/media/video/bt8xx/bttvp.h index 08ef54a..b4d940b 100644 --- a/drivers/media/video/bt8xx/bttvp.h +++ b/drivers/media/video/bt8xx/bttvp.h @@ -267,6 +267,11 @@ int bttv_sub_add_device(struct bttv_core *core, char *name); int bttv_sub_del_devices(struct bttv_core *core); /* ---------------------------------------------------------- */ +/* bttv-cards.c */ + +extern int no_overlay; + +/* ---------------------------------------------------------- */ /* bttv-driver.c */ /* insmod options */ diff --git a/drivers/media/video/btcx-risc.c b/drivers/media/video/btcx-risc.c index f42701f..3324ab3 100644 --- a/drivers/media/video/btcx-risc.c +++ b/drivers/media/video/btcx-risc.c @@ -184,12 +184,12 @@ btcx_sort_clips(struct v4l2_clip *clips, unsigned int nclips) } void -btcx_calc_skips(int line, int width, unsigned int *maxy, +btcx_calc_skips(int line, int width, int *maxy, struct btcx_skiplist *skips, unsigned int *nskips, const struct v4l2_clip *clips, unsigned int nclips) { unsigned int clip,skip; - int end,maxline; + int end, maxline; skip=0; maxline = 9999; diff --git a/drivers/media/video/btcx-risc.h b/drivers/media/video/btcx-risc.h index 861bc81..f8bc6e8 100644 --- a/drivers/media/video/btcx-risc.h +++ b/drivers/media/video/btcx-risc.h @@ -23,7 +23,7 @@ int btcx_screen_clips(int swidth, int sheight, struct v4l2_rect *win, int btcx_align(struct v4l2_rect *win, struct v4l2_clip *clips, unsigned int n, int mask); void btcx_sort_clips(struct v4l2_clip *clips, unsigned int nclips); -void btcx_calc_skips(int line, int width, unsigned int *maxy, +void btcx_calc_skips(int line, int width, int *maxy, struct btcx_skiplist *skips, unsigned int *nskips, const struct v4l2_clip *clips, unsigned int nclips); diff --git a/drivers/media/video/cpia2/cpia2_v4l.c b/drivers/media/video/cpia2/cpia2_v4l.c index 515c8b5..c825706 100644 --- a/drivers/media/video/cpia2/cpia2_v4l.c +++ b/drivers/media/video/cpia2/cpia2_v4l.c @@ -1024,7 +1024,6 @@ static int ioctl_queryctrl(void *arg,struct camera_data *cam) if(cam->params.pnp_id.device_type == DEVICE_STV_672 && cam->params.version.sensor_flags==CPIA2_VP_SENSOR_FLAGS_500){ // Maximum 15fps - int i; for(i=0; imaximum; ++i) { if(framerate_controls[i].value == CPIA2_VP_FRAMERATE_15) { diff --git a/drivers/media/video/cx18/cx18-av-firmware.c b/drivers/media/video/cx18/cx18-av-firmware.c index 834b924..e996a4e 100644 --- a/drivers/media/video/cx18/cx18-av-firmware.c +++ b/drivers/media/video/cx18/cx18-av-firmware.c @@ -32,7 +32,7 @@ int cx18_av_loadfw(struct cx18 *cx) u32 v; const u8 *ptr; int i; - int retries = 0; + int retries1 = 0; if (request_firmware(&fw, FWFILE, &cx->dev->dev) != 0) { CX18_ERR("unable to open firmware %s\n", FWFILE); @@ -41,7 +41,7 @@ int cx18_av_loadfw(struct cx18 *cx) /* The firmware load often has byte errors, so allow for several retries, both at byte level and at the firmware load level. */ - while (retries < 5) { + while (retries1 < 5) { cx18_av_write4(cx, CXADEC_CHIP_CTRL, 0x00010000); cx18_av_write(cx, CXADEC_STD_DET_CTL, 0xf6); @@ -57,9 +57,9 @@ int cx18_av_loadfw(struct cx18 *cx) for (i = 0; i < size; i++) { u32 dl_control = 0x0F000000 | i | ((u32)ptr[i] << 16); u32 value = 0; - int retries; + int retries2; - for (retries = 0; retries < 5; retries++) { + for (retries2 = 0; retries2 < 5; retries2++) { cx18_av_write4(cx, CXADEC_DL_CTL, dl_control); udelay(10); value = cx18_av_read4(cx, CXADEC_DL_CTL); @@ -69,18 +69,18 @@ int cx18_av_loadfw(struct cx18 *cx) the address. We can only write the lower address byte of the address. */ if ((value & 0x3F00) != (dl_control & 0x3F00)) { - retries = 5; + retries2 = 5; break; } } - if (retries >= 5) + if (retries2 >= 5) break; } if (i == size) break; - retries++; + retries1++; } - if (retries >= 5) { + if (retries1 >= 5) { CX18_ERR("unable to load firmware %s\n", FWFILE); release_firmware(fw); return -EIO; diff --git a/drivers/media/video/cx18/cx18-driver.c b/drivers/media/video/cx18/cx18-driver.c index 22434aa..bd18afe 100644 --- a/drivers/media/video/cx18/cx18-driver.c +++ b/drivers/media/video/cx18/cx18-driver.c @@ -74,9 +74,9 @@ static int radio[CX18_MAX_CARDS] = { -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1 }; -static int cardtype_c = 1; -static int tuner_c = 1; -static int radio_c = 1; +static unsigned cardtype_c = 1; +static unsigned tuner_c = 1; +static unsigned radio_c = 1; static char pal[] = "--"; static char secam[] = "--"; static char ntsc[] = "-"; diff --git a/drivers/media/video/cx18/cx18-queue.c b/drivers/media/video/cx18/cx18-queue.c index 8a4dd82..a31da49 100644 --- a/drivers/media/video/cx18/cx18-queue.c +++ b/drivers/media/video/cx18/cx18-queue.c @@ -217,10 +217,10 @@ int cx18_stream_alloc(struct cx18_stream *s) s->name, s->buffers, s->buf_size, s->buffers * s->buf_size / 1024); - if (((char *)&cx->scb->cpu_mdl[cx->mdl_offset + s->buffers] - - (char *)cx->scb) > SCB_RESERVED_SIZE) { - unsigned bufsz = (((char *)cx->scb) + SCB_RESERVED_SIZE - - ((char *)cx->scb->cpu_mdl)); + if (((char __iomem *)&cx->scb->cpu_mdl[cx->mdl_offset + s->buffers] - + (char __iomem *)cx->scb) > SCB_RESERVED_SIZE) { + unsigned bufsz = (((char __iomem *)cx->scb) + SCB_RESERVED_SIZE - + ((char __iomem *)cx->scb->cpu_mdl)); CX18_ERR("Too many buffers, cannot fit in SCB area\n"); CX18_ERR("Max buffers = %zd\n", diff --git a/drivers/media/video/gspca/gspca.c b/drivers/media/video/gspca/gspca.c index 3461bc9..0b292ca 100644 --- a/drivers/media/video/gspca/gspca.c +++ b/drivers/media/video/gspca/gspca.c @@ -1401,7 +1401,7 @@ static int vidioc_dqbuf(struct file *file, void *priv, i = ret; /* frame index */ frame = &gspca_dev->frame[i]; if (gspca_dev->memory == V4L2_MEMORY_USERPTR) { - if (copy_to_user((__u8 *) frame->v4l2_buf.m.userptr, + if (copy_to_user((__u8 __user *) frame->v4l2_buf.m.userptr, frame->data, frame->v4l2_buf.bytesused)) { PDEBUG(D_ERR|D_STREAM, diff --git a/drivers/media/video/ks0127.c b/drivers/media/video/ks0127.c index 4895540..2fd4b4a 100644 --- a/drivers/media/video/ks0127.c +++ b/drivers/media/video/ks0127.c @@ -679,26 +679,27 @@ static int ks0127_command(struct i2c_client *client, case DECODER_ENABLE_OUTPUT: { + int enable; - int *iarg = arg; - int enable = (*iarg != 0); - if (enable) { - dprintk("ks0127: command " + iarg = arg; + enable = (*iarg != 0); + if (enable) { + dprintk("ks0127: command " "DECODER_ENABLE_OUTPUT on " "(%d)\n", enable); - /* All output pins on */ - ks0127_and_or(ks, KS_OFMTA, 0xcf, 0x30); - /* Obey the OEN pin */ - ks0127_and_or(ks, KS_CDEM, 0x7f, 0x00); - } else { - dprintk("ks0127: command " + /* All output pins on */ + ks0127_and_or(ks, KS_OFMTA, 0xcf, 0x30); + /* Obey the OEN pin */ + ks0127_and_or(ks, KS_CDEM, 0x7f, 0x00); + } else { + dprintk("ks0127: command " "DECODER_ENABLE_OUTPUT off " "(%d)\n", enable); - /* Video output pins off */ - ks0127_and_or(ks, KS_OFMTA, 0xcf, 0x00); - /* Ignore the OEN pin */ - ks0127_and_or(ks, KS_CDEM, 0x7f, 0x80); - } + /* Video output pins off */ + ks0127_and_or(ks, KS_OFMTA, 0xcf, 0x00); + /* Ignore the OEN pin */ + ks0127_and_or(ks, KS_CDEM, 0x7f, 0x80); + } } break; diff --git a/drivers/media/video/mxb.c b/drivers/media/video/mxb.c index f68e91f..8ef578c 100644 --- a/drivers/media/video/mxb.c +++ b/drivers/media/video/mxb.c @@ -931,27 +931,29 @@ static int mxb_ioctl(struct saa7146_fh *fh, unsigned int cmd, void *arg) return 0; } -static int std_callback(struct saa7146_dev* dev, struct saa7146_standard *std) +static int std_callback(struct saa7146_dev *dev, struct saa7146_standard *standard) { - struct mxb* mxb = (struct mxb*)dev->ext_priv; + struct mxb *mxb = (struct mxb *)dev->ext_priv; int zero = 0; int one = 1; - if(V4L2_STD_PAL_I == std->id ) { + if (V4L2_STD_PAL_I == standard->id) { v4l2_std_id std = V4L2_STD_PAL_I; + DEB_D(("VIDIOC_S_STD: setting mxb for PAL_I.\n")); /* set the 7146 gpio register -- I don't know what this does exactly */ saa7146_write(dev, GPIO_CTRL, 0x00404050); /* unset the 7111 gpio register -- I don't know what this does exactly */ - mxb->saa7111a->driver->command(mxb->saa7111a,DECODER_SET_GPIO, &zero); + mxb->saa7111a->driver->command(mxb->saa7111a, DECODER_SET_GPIO, &zero); mxb->tuner->driver->command(mxb->tuner, VIDIOC_S_STD, &std); } else { v4l2_std_id std = V4L2_STD_PAL_BG; + DEB_D(("VIDIOC_S_STD: setting mxb for PAL/NTSC/SECAM.\n")); /* set the 7146 gpio register -- I don't know what this does exactly */ saa7146_write(dev, GPIO_CTRL, 0x00404050); /* set the 7111 gpio register -- I don't know what this does exactly */ - mxb->saa7111a->driver->command(mxb->saa7111a,DECODER_SET_GPIO, &one); + mxb->saa7111a->driver->command(mxb->saa7111a, DECODER_SET_GPIO, &one); mxb->tuner->driver->command(mxb->tuner, VIDIOC_S_STD, &std); } return 0; diff --git a/drivers/media/video/ov511.c b/drivers/media/video/ov511.c index 9edaca4..3d3c48d 100644 --- a/drivers/media/video/ov511.c +++ b/drivers/media/video/ov511.c @@ -626,9 +626,9 @@ ov511_i2c_write_internal(struct usb_ov511 *ov, break; /* Retry until idle */ - do + do { rc = reg_r(ov, R511_I2C_CTL); - while (rc > 0 && ((rc&1) == 0)); + } while (rc > 0 && ((rc&1) == 0)); if (rc < 0) break; @@ -703,9 +703,9 @@ ov511_i2c_read_internal(struct usb_ov511 *ov, unsigned char reg) return rc; /* Retry until idle */ - do - rc = reg_r(ov, R511_I2C_CTL); - while (rc > 0 && ((rc&1) == 0)); + do { + rc = reg_r(ov, R511_I2C_CTL); + } while (rc > 0 && ((rc & 1) == 0)); if (rc < 0) return rc; @@ -729,9 +729,9 @@ ov511_i2c_read_internal(struct usb_ov511 *ov, unsigned char reg) return rc; /* Retry until idle */ - do + do { rc = reg_r(ov, R511_I2C_CTL); - while (rc > 0 && ((rc&1) == 0)); + } while (rc > 0 && ((rc&1) == 0)); if (rc < 0) return rc; diff --git a/drivers/media/video/pwc/pwc-ctrl.c b/drivers/media/video/pwc/pwc-ctrl.c index 1cccd5c7..dbc5607 100644 --- a/drivers/media/video/pwc/pwc-ctrl.c +++ b/drivers/media/video/pwc/pwc-ctrl.c @@ -1635,15 +1635,15 @@ int pwc_ioctl(struct pwc_device *pdev, unsigned int cmd, void *arg) case VIDIOCPWCGVIDCMD: { - ARG_DEF(struct pwc_video_command, cmd); - - ARGR(cmd).type = pdev->type; - ARGR(cmd).release = pdev->release; - ARGR(cmd).command_len = pdev->cmd_len; - memcpy(&ARGR(cmd).command_buf, pdev->cmd_buf, pdev->cmd_len); - ARGR(cmd).bandlength = pdev->vbandlength; - ARGR(cmd).frame_size = pdev->frame_size; - ARG_OUT(cmd) + ARG_DEF(struct pwc_video_command, vcmd); + + ARGR(vcmd).type = pdev->type; + ARGR(vcmd).release = pdev->release; + ARGR(vcmd).command_len = pdev->cmd_len; + memcpy(&ARGR(vcmd).command_buf, pdev->cmd_buf, pdev->cmd_len); + ARGR(vcmd).bandlength = pdev->vbandlength; + ARGR(vcmd).frame_size = pdev->frame_size; + ARG_OUT(vcmd) break; } /* diff --git a/drivers/media/video/usbvideo/ibmcam.c b/drivers/media/video/usbvideo/ibmcam.c index 59166b7..cc27efe 100644 --- a/drivers/media/video/usbvideo/ibmcam.c +++ b/drivers/media/video/usbvideo/ibmcam.c @@ -736,12 +736,12 @@ static enum ParseState ibmcam_model2_320x240_parse_lines( * make black color and quit the horizontal scanning loop. */ if (((frame->curline + 2) >= scanHeight) || (i >= scanLength)) { - const int j = i * V4L_BYTES_PER_PIXEL; + const int offset = i * V4L_BYTES_PER_PIXEL; #if USES_IBMCAM_PUTPIXEL /* Refresh 'f' because we don't use it much with PUTPIXEL */ - f = frame->data + (v4l_linesize * frame->curline) + j; + f = frame->data + (v4l_linesize * frame->curline) + offset; #endif - memset(f, 0, v4l_linesize - j); + memset(f, 0, v4l_linesize - offset); break; } -- cgit v0.10.2 From 6c9de52884aeafb05a935467c3a2c05a2d445ab7 Mon Sep 17 00:00:00 2001 From: Andy Walls Date: Wed, 3 Sep 2008 17:11:54 -0300 Subject: V4L/DVB (8769): cx18: Simplify queue flush logic to prevent oops in cx18_flush_queues() cx18: Simplify queue flush logic to prevent oops in cx18_flush_queues(). If accounting of a queue is in error, logic borrowed from ivtv will cause an oops when flushing the queues for a stream. This change greatly simplifies the queue flush logic, and sets the queue back to sane defaults on a flush. Signed-off-by: Andy Walls Signed-off-by: Mauro Carvalho Chehab diff --git a/drivers/media/video/cx18/cx18-queue.c b/drivers/media/video/cx18/cx18-queue.c index a31da49..dbe792a 100644 --- a/drivers/media/video/cx18/cx18-queue.c +++ b/drivers/media/video/cx18/cx18-queue.c @@ -110,99 +110,31 @@ struct cx18_buffer *cx18_queue_get_buf_irq(struct cx18_stream *s, u32 id, return NULL; } -static void cx18_queue_move_buf(struct cx18_stream *s, struct cx18_queue *from, - struct cx18_queue *to, int clear, int full) -{ - struct cx18_buffer *buf = - list_entry(from->list.next, struct cx18_buffer, list); - - list_move_tail(from->list.next, &to->list); - from->buffers--; - from->length -= s->buf_size; - from->bytesused -= buf->bytesused - buf->readpos; - /* special handling for q_free */ - if (clear) - buf->bytesused = buf->readpos = buf->b_flags = 0; - else if (full) { - /* special handling for stolen buffers, assume - all bytes are used. */ - buf->bytesused = s->buf_size; - buf->readpos = buf->b_flags = 0; - } - to->buffers++; - to->length += s->buf_size; - to->bytesused += buf->bytesused - buf->readpos; -} - -/* Move 'needed_bytes' worth of buffers from queue 'from' into queue 'to'. - If 'needed_bytes' == 0, then move all buffers from 'from' into 'to'. - If 'steal' != NULL, then buffers may also taken from that queue if - needed. - - The buffer is automatically cleared if it goes to the free queue. It is - also cleared if buffers need to be taken from the 'steal' queue and - the 'from' queue is the free queue. - - When 'from' is q_free, then needed_bytes is compared to the total - available buffer length, otherwise needed_bytes is compared to the - bytesused value. For the 'steal' queue the total available buffer - length is always used. - - -ENOMEM is returned if the buffers could not be obtained, 0 if all - buffers where obtained from the 'from' list and if non-zero then - the number of stolen buffers is returned. */ -static int cx18_queue_move(struct cx18_stream *s, struct cx18_queue *from, - struct cx18_queue *steal, struct cx18_queue *to, - int needed_bytes) +/* Move all buffers of a queue to q_free, while flushing the buffers */ +static void cx18_queue_flush(struct cx18_stream *s, struct cx18_queue *q) { unsigned long flags; - int rc = 0; - int from_free = from == &s->q_free; - int to_free = to == &s->q_free; - int bytes_available; - - spin_lock_irqsave(&s->qlock, flags); - if (needed_bytes == 0) { - from_free = 1; - needed_bytes = from->length; - } - - bytes_available = from_free ? from->length : from->bytesused; - bytes_available += steal ? steal->length : 0; + struct cx18_buffer *buf; - if (bytes_available < needed_bytes) { - spin_unlock_irqrestore(&s->qlock, flags); - return -ENOMEM; - } - if (from_free) { - u32 old_length = to->length; + if (q == &s->q_free) + return; - while (to->length - old_length < needed_bytes) { - if (list_empty(&from->list)) - from = steal; - if (from == steal) - rc++; /* keep track of 'stolen' buffers */ - cx18_queue_move_buf(s, from, to, 1, 0); - } - } else { - u32 old_bytesused = to->bytesused; - - while (to->bytesused - old_bytesused < needed_bytes) { - if (list_empty(&from->list)) - from = steal; - if (from == steal) - rc++; /* keep track of 'stolen' buffers */ - cx18_queue_move_buf(s, from, to, to_free, rc); - } + spin_lock_irqsave(&s->qlock, flags); + while (!list_empty(&q->list)) { + buf = list_entry(q->list.next, struct cx18_buffer, list); + list_move_tail(q->list.next, &s->q_free.list); + buf->bytesused = buf->readpos = buf->b_flags = 0; + s->q_free.buffers++; + s->q_free.length += s->buf_size; } + cx18_queue_init(q); spin_unlock_irqrestore(&s->qlock, flags); - return rc; } void cx18_flush_queues(struct cx18_stream *s) { - cx18_queue_move(s, &s->q_io, NULL, &s->q_free, 0); - cx18_queue_move(s, &s->q_full, NULL, &s->q_free, 0); + cx18_queue_flush(s, &s->q_io); + cx18_queue_flush(s, &s->q_full); } int cx18_stream_alloc(struct cx18_stream *s) -- cgit v0.10.2 From cba99ae81901fe61ac4b0d65c697474af29dc4ea Mon Sep 17 00:00:00 2001 From: Hans Verkuil Date: Wed, 3 Sep 2008 17:11:58 -0300 Subject: V4L/DVB (8778): radio: fix incorrect video_register_device result check Signed-off-by: Hans Verkuil Signed-off-by: Mauro Carvalho Chehab diff --git a/drivers/media/radio/dsbr100.c b/drivers/media/radio/dsbr100.c index 1ed88f3..70c65a7 100644 --- a/drivers/media/radio/dsbr100.c +++ b/drivers/media/radio/dsbr100.c @@ -493,7 +493,7 @@ static int usb_dsbr100_probe(struct usb_interface *intf, radio->usbdev = interface_to_usbdev(intf); radio->curfreq = FREQ_MIN*FREQ_MUL; video_set_drvdata(radio->videodev, radio); - if (video_register_device(radio->videodev, VFL_TYPE_RADIO,radio_nr)) { + if (video_register_device(radio->videodev, VFL_TYPE_RADIO, radio_nr) < 0) { warn("Could not register video device"); video_device_release(radio->videodev); kfree(radio->transfer_buffer); diff --git a/drivers/media/radio/radio-aimslab.c b/drivers/media/radio/radio-aimslab.c index eba9209..1f064f4 100644 --- a/drivers/media/radio/radio-aimslab.c +++ b/drivers/media/radio/radio-aimslab.c @@ -426,8 +426,7 @@ static int __init rtrack_init(void) rtrack_radio.priv=&rtrack_unit; - if(video_register_device(&rtrack_radio, VFL_TYPE_RADIO, radio_nr)==-1) - { + if (video_register_device(&rtrack_radio, VFL_TYPE_RADIO, radio_nr) < 0) { release_region(io, 2); return -EINVAL; } diff --git a/drivers/media/radio/radio-aztech.c b/drivers/media/radio/radio-aztech.c index 3fe5504..628c689 100644 --- a/drivers/media/radio/radio-aztech.c +++ b/drivers/media/radio/radio-aztech.c @@ -394,8 +394,7 @@ static int __init aztech_init(void) mutex_init(&lock); aztech_radio.priv=&aztech_unit; - if(video_register_device(&aztech_radio, VFL_TYPE_RADIO, radio_nr)==-1) - { + if (video_register_device(&aztech_radio, VFL_TYPE_RADIO, radio_nr) < 0) { release_region(io,2); return -EINVAL; } diff --git a/drivers/media/radio/radio-cadet.c b/drivers/media/radio/radio-cadet.c index 6166e72..04c3698 100644 --- a/drivers/media/radio/radio-cadet.c +++ b/drivers/media/radio/radio-cadet.c @@ -682,7 +682,7 @@ static int __init cadet_init(void) } if (!request_region(io,2,"cadet")) goto fail; - if(video_register_device(&cadet_radio,VFL_TYPE_RADIO,radio_nr)==-1) { + if (video_register_device(&cadet_radio, VFL_TYPE_RADIO, radio_nr) < 0) { release_region(io,2); goto fail; } diff --git a/drivers/media/radio/radio-gemtek-pci.c b/drivers/media/radio/radio-gemtek-pci.c index 36e754e..5cd7f03 100644 --- a/drivers/media/radio/radio-gemtek-pci.c +++ b/drivers/media/radio/radio-gemtek-pci.c @@ -425,7 +425,7 @@ static int __devinit gemtek_pci_probe( struct pci_dev *pci_dev, const struct pci } *devradio = vdev_template; - if ( video_register_device( devradio, VFL_TYPE_RADIO , nr_radio) == -1 ) { + if (video_register_device(devradio, VFL_TYPE_RADIO, nr_radio) < 0) { kfree( devradio ); goto err_video; } diff --git a/drivers/media/radio/radio-gemtek.c b/drivers/media/radio/radio-gemtek.c index 2b1a622..0a0f956 100644 --- a/drivers/media/radio/radio-gemtek.c +++ b/drivers/media/radio/radio-gemtek.c @@ -612,8 +612,7 @@ static int __init gemtek_init(void) gemtek_radio.priv = &gemtek_unit; - if (video_register_device(&gemtek_radio, VFL_TYPE_RADIO, - radio_nr) == -1) { + if (video_register_device(&gemtek_radio, VFL_TYPE_RADIO, radio_nr) < 0) { release_region(io, 1); return -EBUSY; } diff --git a/drivers/media/radio/radio-maestro.c b/drivers/media/radio/radio-maestro.c index 0ada1c6..9ef0a76 100644 --- a/drivers/media/radio/radio-maestro.c +++ b/drivers/media/radio/radio-maestro.c @@ -409,8 +409,7 @@ static int __devinit maestro_probe(struct pci_dev *pdev, video_set_drvdata(maestro_radio_inst, radio_unit); pci_set_drvdata(pdev, maestro_radio_inst); - retval = video_register_device(maestro_radio_inst, VFL_TYPE_RADIO, - radio_nr); + retval = video_register_device(maestro_radio_inst, VFL_TYPE_RADIO, radio_nr); if (retval) { printk(KERN_ERR "can't register video device!\n"); goto errfr1; diff --git a/drivers/media/radio/radio-maxiradio.c b/drivers/media/radio/radio-maxiradio.c index e210da1..0cc6fcb 100644 --- a/drivers/media/radio/radio-maxiradio.c +++ b/drivers/media/radio/radio-maxiradio.c @@ -410,7 +410,7 @@ static int __devinit maxiradio_init_one(struct pci_dev *pdev, const struct pci_d mutex_init(&radio_unit.lock); maxiradio_radio.priv = &radio_unit; - if (video_register_device(&maxiradio_radio, VFL_TYPE_RADIO, radio_nr)==-1) { + if (video_register_device(&maxiradio_radio, VFL_TYPE_RADIO, radio_nr) < 0) { printk("radio-maxiradio: can't register device!"); goto err_out_free_region; } diff --git a/drivers/media/radio/radio-rtrack2.c b/drivers/media/radio/radio-rtrack2.c index e2dde08..6d820e2 100644 --- a/drivers/media/radio/radio-rtrack2.c +++ b/drivers/media/radio/radio-rtrack2.c @@ -332,8 +332,7 @@ static int __init rtrack2_init(void) rtrack2_radio.priv=&rtrack2_unit; spin_lock_init(&lock); - if(video_register_device(&rtrack2_radio, VFL_TYPE_RADIO, radio_nr)==-1) - { + if (video_register_device(&rtrack2_radio, VFL_TYPE_RADIO, radio_nr) < 0) { release_region(io, 4); return -EINVAL; } diff --git a/drivers/media/radio/radio-sf16fmi.c b/drivers/media/radio/radio-sf16fmi.c index bb5d92f..0d478f5 100644 --- a/drivers/media/radio/radio-sf16fmi.c +++ b/drivers/media/radio/radio-sf16fmi.c @@ -377,7 +377,7 @@ static int __init fmi_init(void) mutex_init(&lock); - if (video_register_device(&fmi_radio, VFL_TYPE_RADIO, radio_nr) == -1) { + if (video_register_device(&fmi_radio, VFL_TYPE_RADIO, radio_nr) < 0) { release_region(io, 2); return -EINVAL; } diff --git a/drivers/media/radio/radio-si470x.c b/drivers/media/radio/radio-si470x.c index a4984ff..16c7ef2 100644 --- a/drivers/media/radio/radio-si470x.c +++ b/drivers/media/radio/radio-si470x.c @@ -1694,8 +1694,8 @@ static int si470x_usb_driver_probe(struct usb_interface *intf, INIT_DELAYED_WORK(&radio->work, si470x_work); /* register video device */ - if (video_register_device(radio->videodev, VFL_TYPE_RADIO, radio_nr)) { - retval = -EIO; + retval = video_register_device(radio->videodev, VFL_TYPE_RADIO, radio_nr); + if (retval) { printk(KERN_WARNING DRIVER_NAME ": Could not register video device\n"); goto err_all; diff --git a/drivers/media/radio/radio-terratec.c b/drivers/media/radio/radio-terratec.c index cefa44f..0876fec 100644 --- a/drivers/media/radio/radio-terratec.c +++ b/drivers/media/radio/radio-terratec.c @@ -405,8 +405,7 @@ static int __init terratec_init(void) spin_lock_init(&lock); - if(video_register_device(&terratec_radio, VFL_TYPE_RADIO, radio_nr)==-1) - { + if (video_register_device(&terratec_radio, VFL_TYPE_RADIO, radio_nr) < 0) { release_region(io,2); return -EINVAL; } diff --git a/drivers/media/radio/radio-trust.c b/drivers/media/radio/radio-trust.c index d70172d..1931619 100644 --- a/drivers/media/radio/radio-trust.c +++ b/drivers/media/radio/radio-trust.c @@ -378,8 +378,7 @@ static int __init trust_init(void) printk(KERN_ERR "trust: port 0x%x already in use\n", io); return -EBUSY; } - if(video_register_device(&trust_radio, VFL_TYPE_RADIO, radio_nr)==-1) - { + if (video_register_device(&trust_radio, VFL_TYPE_RADIO, radio_nr) < 0) { release_region(io, 2); return -EINVAL; } diff --git a/drivers/media/radio/radio-zoltrix.c b/drivers/media/radio/radio-zoltrix.c index 9f17a33..51d57ed 100644 --- a/drivers/media/radio/radio-zoltrix.c +++ b/drivers/media/radio/radio-zoltrix.c @@ -446,8 +446,7 @@ static int __init zoltrix_init(void) return -EBUSY; } - if (video_register_device(&zoltrix_radio, VFL_TYPE_RADIO, radio_nr) == -1) - { + if (video_register_device(&zoltrix_radio, VFL_TYPE_RADIO, radio_nr) < 0) { release_region(io, 2); return -EINVAL; } -- cgit v0.10.2 From dc60de338f4b2d445a24d4e36bbc994f3badb406 Mon Sep 17 00:00:00 2001 From: Hans Verkuil Date: Wed, 3 Sep 2008 17:11:58 -0300 Subject: V4L/DVB (8779): v4l: fix more incorrect video_register_device result checks Signed-off-by: Hans Verkuil Signed-off-by: Mauro Carvalho Chehab diff --git a/drivers/media/video/bw-qcam.c b/drivers/media/video/bw-qcam.c index d3b3268..6e39e25 100644 --- a/drivers/media/video/bw-qcam.c +++ b/drivers/media/video/bw-qcam.c @@ -946,8 +946,7 @@ static int init_bwqcam(struct parport *port) printk(KERN_INFO "Connectix Quickcam on %s\n", qcam->pport->name); - if(video_register_device(&qcam->vdev, VFL_TYPE_GRABBER, video_nr)==-1) - { + if (video_register_device(&qcam->vdev, VFL_TYPE_GRABBER, video_nr) < 0) { parport_unregister_device(qcam->pdev); kfree(qcam); return -ENODEV; diff --git a/drivers/media/video/c-qcam.c b/drivers/media/video/c-qcam.c index fe9379b..7f6c6b4 100644 --- a/drivers/media/video/c-qcam.c +++ b/drivers/media/video/c-qcam.c @@ -787,8 +787,7 @@ static int init_cqcam(struct parport *port) parport_release(qcam->pdev); - if (video_register_device(&qcam->vdev, VFL_TYPE_GRABBER, video_nr)==-1) - { + if (video_register_device(&qcam->vdev, VFL_TYPE_GRABBER, video_nr) < 0) { printk(KERN_ERR "Unable to register Colour QuickCam on %s\n", qcam->pport->name); parport_unregister_device(qcam->pdev); diff --git a/drivers/media/video/cpia.c b/drivers/media/video/cpia.c index dc8cc61..a661800 100644 --- a/drivers/media/video/cpia.c +++ b/drivers/media/video/cpia.c @@ -3955,7 +3955,7 @@ struct cam_data *cpia_register_camera(struct cpia_camera_ops *ops, void *lowleve camera->lowlevel_data = lowlevel; /* register v4l device */ - if (video_register_device(&camera->vdev, VFL_TYPE_GRABBER, video_nr) == -1) { + if (video_register_device(&camera->vdev, VFL_TYPE_GRABBER, video_nr) < 0) { kfree(camera); printk(KERN_DEBUG "video_register_device failed\n"); return NULL; diff --git a/drivers/media/video/cpia2/cpia2_v4l.c b/drivers/media/video/cpia2/cpia2_v4l.c index c825706..eb9f15c 100644 --- a/drivers/media/video/cpia2/cpia2_v4l.c +++ b/drivers/media/video/cpia2/cpia2_v4l.c @@ -1958,8 +1958,7 @@ int cpia2_register_camera(struct camera_data *cam) reset_camera_struct_v4l(cam); /* register v4l device */ - if (video_register_device - (cam->vdev, VFL_TYPE_GRABBER, video_nr) == -1) { + if (video_register_device(cam->vdev, VFL_TYPE_GRABBER, video_nr) < 0) { ERR("video_register_device failed\n"); video_device_release(cam->vdev); return -ENODEV; diff --git a/drivers/media/video/se401.c b/drivers/media/video/se401.c index f481277..acceed5 100644 --- a/drivers/media/video/se401.c +++ b/drivers/media/video/se401.c @@ -1397,7 +1397,7 @@ static int se401_probe(struct usb_interface *intf, mutex_init(&se401->lock); wmb(); - if (video_register_device(&se401->vdev, VFL_TYPE_GRABBER, video_nr) == -1) { + if (video_register_device(&se401->vdev, VFL_TYPE_GRABBER, video_nr) < 0) { kfree(se401); err("video_register_device failed"); return -EIO; diff --git a/drivers/media/video/stv680.c b/drivers/media/video/stv680.c index 56dc3d6..dce9474 100644 --- a/drivers/media/video/stv680.c +++ b/drivers/media/video/stv680.c @@ -1462,7 +1462,7 @@ static int stv680_probe (struct usb_interface *intf, const struct usb_device_id mutex_init (&stv680->lock); wmb (); - if (video_register_device (stv680->vdev, VFL_TYPE_GRABBER, video_nr) == -1) { + if (video_register_device(stv680->vdev, VFL_TYPE_GRABBER, video_nr) < 0) { PDEBUG (0, "STV(e): video_register_device failed"); retval = -EIO; goto error_vdev; diff --git a/drivers/media/video/usbvideo/vicam.c b/drivers/media/video/usbvideo/vicam.c index b779245..2eb4582 100644 --- a/drivers/media/video/usbvideo/vicam.c +++ b/drivers/media/video/usbvideo/vicam.c @@ -866,7 +866,7 @@ vicam_probe( struct usb_interface *intf, const struct usb_device_id *id) cam->udev = dev; cam->bulkEndpoint = bulkEndpoint; - if (video_register_device(&cam->vdev, VFL_TYPE_GRABBER, -1) == -1) { + if (video_register_device(&cam->vdev, VFL_TYPE_GRABBER, -1) < 0) { kfree(cam); printk(KERN_WARNING "video_register_device failed\n"); return -EIO; diff --git a/drivers/media/video/w9966.c b/drivers/media/video/w9966.c index 9402f40..2ff00bc 100644 --- a/drivers/media/video/w9966.c +++ b/drivers/media/video/w9966.c @@ -334,7 +334,7 @@ static int w9966_init(struct w9966_dev* cam, struct parport* port) memcpy(&cam->vdev, &w9966_template, sizeof(struct video_device)); cam->vdev.priv = cam; - if (video_register_device(&cam->vdev, VFL_TYPE_GRABBER, video_nr) == -1) + if (video_register_device(&cam->vdev, VFL_TYPE_GRABBER, video_nr) < 0) return -1; w9966_setState(cam, W9966_STATE_VDEV, W9966_STATE_VDEV); -- cgit v0.10.2 From c5bf204f42423f49d7ea34f14eef92780204e168 Mon Sep 17 00:00:00 2001 From: Hans Verkuil Date: Wed, 3 Sep 2008 17:12:09 -0300 Subject: V4L/DVB (8790): saa7115: call i2c_set_clientdata only when state != NULL Not a bug as such, but it looks really strange doing this before checking whether the state structure could be allocated. Signed-off-by: Hans Verkuil Signed-off-by: Mauro Carvalho Chehab diff --git a/drivers/media/video/saa7115.c b/drivers/media/video/saa7115.c index bcd1c8f..ad733ca 100644 --- a/drivers/media/video/saa7115.c +++ b/drivers/media/video/saa7115.c @@ -1489,10 +1489,9 @@ static int saa7115_probe(struct i2c_client *client, client->addr << 1, client->adapter->name); state = kzalloc(sizeof(struct saa711x_state), GFP_KERNEL); - i2c_set_clientdata(client, state); - if (state == NULL) { + if (state == NULL) return -ENOMEM; - } + i2c_set_clientdata(client, state); state->input = -1; state->output = SAA7115_IPORT_ON; state->enable = 1; -- cgit v0.10.2 From 4fc85c74b431ba6e9a8e295e090cd532667b984d Mon Sep 17 00:00:00 2001 From: Steven Toth Date: Wed, 3 Sep 2008 17:12:12 -0300 Subject: V4L/DVB (8803): s5h1409: Enable QAM_AUTO mode If apps pass QAM_AUTO then we need to obey it. Signed-off-by: Steven Toth Signed-off-by: Mauro Carvalho Chehab diff --git a/drivers/media/dvb/frontends/s5h1409.c b/drivers/media/dvb/frontends/s5h1409.c index 5ddb2dc..0a56ae8 100644 --- a/drivers/media/dvb/frontends/s5h1409.c +++ b/drivers/media/dvb/frontends/s5h1409.c @@ -404,6 +404,7 @@ static int s5h1409_enable_modulation(struct dvb_frontend* fe, break; case QAM_64: case QAM_256: + case QAM_AUTO: dprintk("%s() QAM_AUTO (64/256)\n", __func__); if (state->if_freq != S5H1409_QAM_IF_FREQ) s5h1409_set_if_freq(fe, S5H1409_QAM_IF_FREQ); -- cgit v0.10.2 From 5ca947a999c5ea5147cce3e42a9d790d3b87a246 Mon Sep 17 00:00:00 2001 From: Steven Toth Date: Wed, 3 Sep 2008 17:12:12 -0300 Subject: V4L/DVB (8804): s5h1411: Enable QAM_AUTO mode If apps pass QAM_AUTO then we need to obey it. Signed-off-by: Steven Toth Signed-off-by: Mauro Carvalho Chehab diff --git a/drivers/media/dvb/frontends/s5h1411.c b/drivers/media/dvb/frontends/s5h1411.c index cff360c..763ac10 100644 --- a/drivers/media/dvb/frontends/s5h1411.c +++ b/drivers/media/dvb/frontends/s5h1411.c @@ -488,6 +488,7 @@ static int s5h1411_enable_modulation(struct dvb_frontend *fe, break; case QAM_64: case QAM_256: + case QAM_AUTO: dprintk("%s() QAM_AUTO (64/256)\n", __func__); s5h1411_set_if_freq(fe, state->config->qam_if); s5h1411_writereg(state, S5H1411_I2C_TOP_ADDR, 0x00, 0x0171); -- cgit v0.10.2 From 6d8976164dd7d10d25fe940b8546265f60ad52cd Mon Sep 17 00:00:00 2001 From: Steven Toth Date: Wed, 3 Sep 2008 17:12:12 -0300 Subject: V4L/DVB (8805): Steven Toth email address change I need this so I can better isolate my linux email from my corporate email. Signed-off-by: Steven Toth Signed-off-by: Mauro Carvalho Chehab diff --git a/drivers/media/common/tuners/mt2131.c b/drivers/media/common/tuners/mt2131.c index e254bcf..e8d3c48 100644 --- a/drivers/media/common/tuners/mt2131.c +++ b/drivers/media/common/tuners/mt2131.c @@ -1,7 +1,7 @@ /* * Driver for Microtune MT2131 "QAM/8VSB single chip tuner" * - * Copyright (c) 2006 Steven Toth + * Copyright (c) 2006 Steven Toth * * 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 diff --git a/drivers/media/common/tuners/mt2131.h b/drivers/media/common/tuners/mt2131.h index cd8376f..6632de6 100644 --- a/drivers/media/common/tuners/mt2131.h +++ b/drivers/media/common/tuners/mt2131.h @@ -1,7 +1,7 @@ /* * Driver for Microtune MT2131 "QAM/8VSB single chip tuner" * - * Copyright (c) 2006 Steven Toth + * Copyright (c) 2006 Steven Toth * * 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 diff --git a/drivers/media/common/tuners/mt2131_priv.h b/drivers/media/common/tuners/mt2131_priv.h index e930759..4e05a67 100644 --- a/drivers/media/common/tuners/mt2131_priv.h +++ b/drivers/media/common/tuners/mt2131_priv.h @@ -1,7 +1,7 @@ /* * Driver for Microtune MT2131 "QAM/8VSB single chip tuner" * - * Copyright (c) 2006 Steven Toth + * Copyright (c) 2006 Steven Toth * * 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 diff --git a/drivers/media/common/tuners/mxl5005s.c b/drivers/media/common/tuners/mxl5005s.c index 0dc2bef..227642b 100644 --- a/drivers/media/common/tuners/mxl5005s.c +++ b/drivers/media/common/tuners/mxl5005s.c @@ -2,7 +2,7 @@ MaxLinear MXL5005S VSB/QAM/DVBT tuner driver Copyright (C) 2008 MaxLinear - Copyright (C) 2006 Steven Toth + Copyright (C) 2006 Steven Toth Functions: mxl5005s_reset() mxl5005s_writereg() @@ -3837,7 +3837,7 @@ static u16 MXL_Hystersis_Test(struct dvb_frontend *fe, int Hystersis) /* ---------------------------------------------------------------- * Begin: Everything after here is new code to adapt the * proprietary Realtek driver into a Linux API tuner. - * Copyright (C) 2008 Steven Toth + * Copyright (C) 2008 Steven Toth */ static int mxl5005s_reset(struct dvb_frontend *fe) { diff --git a/drivers/media/common/tuners/mxl5005s.h b/drivers/media/common/tuners/mxl5005s.h index 396db15..7ac6815 100644 --- a/drivers/media/common/tuners/mxl5005s.h +++ b/drivers/media/common/tuners/mxl5005s.h @@ -2,7 +2,7 @@ MaxLinear MXL5005S VSB/QAM/DVBT tuner driver Copyright (C) 2008 MaxLinear - Copyright (C) 2008 Steven Toth + Copyright (C) 2008 Steven Toth 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 diff --git a/drivers/media/common/tuners/xc5000.c b/drivers/media/common/tuners/xc5000.c index 5f99de0..dcddfa8 100644 --- a/drivers/media/common/tuners/xc5000.c +++ b/drivers/media/common/tuners/xc5000.c @@ -2,7 +2,7 @@ * Driver for Xceive XC5000 "QAM/8VSB single chip tuner" * * Copyright (c) 2007 Xceive Corporation - * Copyright (c) 2007 Steven Toth + * Copyright (c) 2007 Steven Toth * * 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 diff --git a/drivers/media/common/tuners/xc5000.h b/drivers/media/common/tuners/xc5000.h index c910715..5389f74 100644 --- a/drivers/media/common/tuners/xc5000.h +++ b/drivers/media/common/tuners/xc5000.h @@ -1,7 +1,7 @@ /* * Driver for Xceive XC5000 "QAM/8VSB single chip tuner" * - * Copyright (c) 2007 Steven Toth + * Copyright (c) 2007 Steven Toth * * 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 diff --git a/drivers/media/common/tuners/xc5000_priv.h b/drivers/media/common/tuners/xc5000_priv.h index a72a988..b2a0074 100644 --- a/drivers/media/common/tuners/xc5000_priv.h +++ b/drivers/media/common/tuners/xc5000_priv.h @@ -1,7 +1,7 @@ /* * Driver for Xceive XC5000 "QAM/8VSB single chip tuner" * - * Copyright (c) 2007 Steven Toth + * Copyright (c) 2007 Steven Toth * * 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 diff --git a/drivers/media/dvb/frontends/au8522.c b/drivers/media/dvb/frontends/au8522.c index 5a6cbb4..0b82cc2 100644 --- a/drivers/media/dvb/frontends/au8522.c +++ b/drivers/media/dvb/frontends/au8522.c @@ -1,7 +1,7 @@ /* Auvitek AU8522 QAM/8VSB demodulator driver - Copyright (C) 2008 Steven Toth + Copyright (C) 2008 Steven Toth 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 diff --git a/drivers/media/dvb/frontends/au8522.h b/drivers/media/dvb/frontends/au8522.h index afc9af2..595915a 100644 --- a/drivers/media/dvb/frontends/au8522.h +++ b/drivers/media/dvb/frontends/au8522.h @@ -1,7 +1,7 @@ /* Auvitek AU8522 QAM/8VSB demodulator driver - Copyright (C) 2008 Steven Toth + Copyright (C) 2008 Steven Toth 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 diff --git a/drivers/media/dvb/frontends/cx22702.c b/drivers/media/dvb/frontends/cx22702.c index cc1db4e..9430e03 100644 --- a/drivers/media/dvb/frontends/cx22702.c +++ b/drivers/media/dvb/frontends/cx22702.c @@ -7,7 +7,7 @@ Copyright (C) 2001-2002 Convergence Integrated Media GmbH Holger Waechtler - Copyright (C) 2004 Steven Toth + Copyright (C) 2004 Steven Toth 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 diff --git a/drivers/media/dvb/frontends/cx22702.h b/drivers/media/dvb/frontends/cx22702.h index 8af766a..b1e465c 100644 --- a/drivers/media/dvb/frontends/cx22702.h +++ b/drivers/media/dvb/frontends/cx22702.h @@ -7,7 +7,7 @@ Copyright (C) 2001-2002 Convergence Integrated Media GmbH Holger Waechtler - Copyright (C) 2004 Steven Toth + Copyright (C) 2004 Steven Toth 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 diff --git a/drivers/media/dvb/frontends/cx24123.c b/drivers/media/dvb/frontends/cx24123.c index 7f68d78..386bd74 100644 --- a/drivers/media/dvb/frontends/cx24123.c +++ b/drivers/media/dvb/frontends/cx24123.c @@ -1,7 +1,7 @@ /* * Conexant cx24123/cx24109 - DVB QPSK Satellite demod/tuner driver * - * Copyright (C) 2005 Steven Toth + * Copyright (C) 2005 Steven Toth * * Support for KWorld DVB-S 100 by Vadim Catana * diff --git a/drivers/media/dvb/frontends/cx24123.h b/drivers/media/dvb/frontends/cx24123.h index 81ebc3d..cc6b411 100644 --- a/drivers/media/dvb/frontends/cx24123.h +++ b/drivers/media/dvb/frontends/cx24123.h @@ -1,7 +1,7 @@ /* Conexant cx24123/cx24109 - DVB QPSK Satellite demod/tuner driver - Copyright (C) 2005 Steven Toth + Copyright (C) 2005 Steven Toth 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 diff --git a/drivers/media/dvb/frontends/s5h1409.c b/drivers/media/dvb/frontends/s5h1409.c index 0a56ae8..7500a1c 100644 --- a/drivers/media/dvb/frontends/s5h1409.c +++ b/drivers/media/dvb/frontends/s5h1409.c @@ -1,7 +1,7 @@ /* Samsung S5H1409 VSB/QAM demodulator driver - Copyright (C) 2006 Steven Toth + Copyright (C) 2006 Steven Toth 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 diff --git a/drivers/media/dvb/frontends/s5h1409.h b/drivers/media/dvb/frontends/s5h1409.h index 59f4335..d1a1d2e 100644 --- a/drivers/media/dvb/frontends/s5h1409.h +++ b/drivers/media/dvb/frontends/s5h1409.h @@ -1,7 +1,7 @@ /* Samsung S5H1409 VSB/QAM demodulator driver - Copyright (C) 2006 Steven Toth + Copyright (C) 2006 Steven Toth 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 diff --git a/drivers/media/dvb/frontends/s5h1411.c b/drivers/media/dvb/frontends/s5h1411.c index 763ac10..2da1a37 100644 --- a/drivers/media/dvb/frontends/s5h1411.c +++ b/drivers/media/dvb/frontends/s5h1411.c @@ -1,7 +1,7 @@ /* Samsung S5H1411 VSB/QAM demodulator driver - Copyright (C) 2008 Steven Toth + Copyright (C) 2008 Steven Toth 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 diff --git a/drivers/media/dvb/frontends/s5h1411.h b/drivers/media/dvb/frontends/s5h1411.h index 1855f64..7d542bc 100644 --- a/drivers/media/dvb/frontends/s5h1411.h +++ b/drivers/media/dvb/frontends/s5h1411.h @@ -1,7 +1,7 @@ /* Samsung S5H1411 VSB/QAM demodulator driver - Copyright (C) 2008 Steven Toth + Copyright (C) 2008 Steven Toth 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 diff --git a/drivers/media/dvb/frontends/tda10048.c b/drivers/media/dvb/frontends/tda10048.c index 0ab8d86b..7727099 100644 --- a/drivers/media/dvb/frontends/tda10048.c +++ b/drivers/media/dvb/frontends/tda10048.c @@ -1,7 +1,7 @@ /* NXP TDA10048HN DVB OFDM demodulator driver - Copyright (C) 2008 Steven Toth + Copyright (C) 2008 Steven Toth 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 diff --git a/drivers/media/dvb/frontends/tda10048.h b/drivers/media/dvb/frontends/tda10048.h index 2b5c78e..0457b24 100644 --- a/drivers/media/dvb/frontends/tda10048.h +++ b/drivers/media/dvb/frontends/tda10048.h @@ -1,7 +1,7 @@ /* NXP TDA10048HN DVB OFDM demodulator driver - Copyright (C) 2008 Steven Toth + Copyright (C) 2008 Steven Toth 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 diff --git a/drivers/media/video/au0828/au0828-cards.c b/drivers/media/video/au0828/au0828-cards.c index 14b9fc9..ed48908 100644 --- a/drivers/media/video/au0828/au0828-cards.c +++ b/drivers/media/video/au0828/au0828-cards.c @@ -1,7 +1,7 @@ /* * Driver for the Auvitek USB bridge * - * Copyright (c) 2008 Steven Toth + * Copyright (c) 2008 Steven Toth * * 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 diff --git a/drivers/media/video/au0828/au0828-cards.h b/drivers/media/video/au0828/au0828-cards.h index 102ed03..48a1882 100644 --- a/drivers/media/video/au0828/au0828-cards.h +++ b/drivers/media/video/au0828/au0828-cards.h @@ -1,7 +1,7 @@ /* * Driver for the Auvitek USB bridge * - * Copyright (c) 2008 Steven Toth + * Copyright (c) 2008 Steven Toth * * 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 diff --git a/drivers/media/video/au0828/au0828-core.c b/drivers/media/video/au0828/au0828-core.c index 54bfc0f..d856de9 100644 --- a/drivers/media/video/au0828/au0828-core.c +++ b/drivers/media/video/au0828/au0828-core.c @@ -1,7 +1,7 @@ /* * Driver for the Auvitek USB bridge * - * Copyright (c) 2008 Steven Toth + * Copyright (c) 2008 Steven Toth * * 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 @@ -252,5 +252,5 @@ module_init(au0828_init); module_exit(au0828_exit); MODULE_DESCRIPTION("Driver for Auvitek AU0828 based products"); -MODULE_AUTHOR("Steven Toth "); +MODULE_AUTHOR("Steven Toth "); MODULE_LICENSE("GPL"); diff --git a/drivers/media/video/au0828/au0828-dvb.c b/drivers/media/video/au0828/au0828-dvb.c index 1948653..ba94be7 100644 --- a/drivers/media/video/au0828/au0828-dvb.c +++ b/drivers/media/video/au0828/au0828-dvb.c @@ -1,7 +1,7 @@ /* * Driver for the Auvitek USB bridge * - * Copyright (c) 2008 Steven Toth + * Copyright (c) 2008 Steven Toth * * 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 diff --git a/drivers/media/video/au0828/au0828-i2c.c b/drivers/media/video/au0828/au0828-i2c.c index 741a493..d618fba 100644 --- a/drivers/media/video/au0828/au0828-i2c.c +++ b/drivers/media/video/au0828/au0828-i2c.c @@ -1,7 +1,7 @@ /* * Driver for the Auvitek AU0828 USB bridge * - * Copyright (c) 2008 Steven Toth + * Copyright (c) 2008 Steven Toth * * 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 diff --git a/drivers/media/video/au0828/au0828-reg.h b/drivers/media/video/au0828/au0828-reg.h index 3982755..1e87fa0c6 100644 --- a/drivers/media/video/au0828/au0828-reg.h +++ b/drivers/media/video/au0828/au0828-reg.h @@ -1,7 +1,7 @@ /* * Driver for the Auvitek USB bridge * - * Copyright (c) 2008 Steven Toth + * Copyright (c) 2008 Steven Toth * * 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 diff --git a/drivers/media/video/au0828/au0828.h b/drivers/media/video/au0828/au0828.h index 7beb571..4f10ff3 100644 --- a/drivers/media/video/au0828/au0828.h +++ b/drivers/media/video/au0828/au0828.h @@ -1,7 +1,7 @@ /* * Driver for the Auvitek AU0828 USB bridge * - * Copyright (c) 2008 Steven Toth + * Copyright (c) 2008 Steven Toth * * 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 diff --git a/drivers/media/video/cx18/cx18-dvb.c b/drivers/media/video/cx18/cx18-dvb.c index cae3898..1e420a8 100644 --- a/drivers/media/video/cx18/cx18-dvb.c +++ b/drivers/media/video/cx18/cx18-dvb.c @@ -1,7 +1,7 @@ /* * cx18 functions for DVB support * - * Copyright (c) 2008 Steven Toth + * Copyright (c) 2008 Steven Toth * * 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 diff --git a/drivers/media/video/cx18/cx18-dvb.h b/drivers/media/video/cx18/cx18-dvb.h index d6a6ccd..bf8d8f6 100644 --- a/drivers/media/video/cx18/cx18-dvb.h +++ b/drivers/media/video/cx18/cx18-dvb.h @@ -1,7 +1,7 @@ /* * cx18 functions for DVB support * - * Copyright (c) 2008 Steven Toth + * Copyright (c) 2008 Steven Toth * * 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 diff --git a/drivers/media/video/cx23885/cx23885-417.c b/drivers/media/video/cx23885/cx23885-417.c index 8118091..7b0e8c0 100644 --- a/drivers/media/video/cx23885/cx23885-417.c +++ b/drivers/media/video/cx23885/cx23885-417.c @@ -4,7 +4,7 @@ * * (c) 2004 Jelle Foks * (c) 2004 Gerd Knorr - * (c) 2008 Steven Toth + * (c) 2008 Steven Toth * - CX23885/7/8 support * * Includes parts from the ivtv driver( http://ivtv.sourceforge.net/), diff --git a/drivers/media/video/cx23885/cx23885-cards.c b/drivers/media/video/cx23885/cx23885-cards.c index a19de85..c36d3f6 100644 --- a/drivers/media/video/cx23885/cx23885-cards.c +++ b/drivers/media/video/cx23885/cx23885-cards.c @@ -1,7 +1,7 @@ /* * Driver for the Conexant CX23885 PCIe bridge * - * Copyright (c) 2006 Steven Toth + * Copyright (c) 2006 Steven Toth * * 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 diff --git a/drivers/media/video/cx23885/cx23885-core.c b/drivers/media/video/cx23885/cx23885-core.c index 6286a9c..25fb099 100644 --- a/drivers/media/video/cx23885/cx23885-core.c +++ b/drivers/media/video/cx23885/cx23885-core.c @@ -1,7 +1,7 @@ /* * Driver for the Conexant CX23885 PCIe bridge * - * Copyright (c) 2006 Steven Toth + * Copyright (c) 2006 Steven Toth * * 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 @@ -33,7 +33,7 @@ #include "cx23885.h" MODULE_DESCRIPTION("Driver for cx23885 based TV cards"); -MODULE_AUTHOR("Steven Toth "); +MODULE_AUTHOR("Steven Toth "); MODULE_LICENSE("GPL"); static unsigned int debug; diff --git a/drivers/media/video/cx23885/cx23885-dvb.c b/drivers/media/video/cx23885/cx23885-dvb.c index 0a2e655..291b9d0 100644 --- a/drivers/media/video/cx23885/cx23885-dvb.c +++ b/drivers/media/video/cx23885/cx23885-dvb.c @@ -1,7 +1,7 @@ /* * Driver for the Conexant CX23885 PCIe bridge * - * Copyright (c) 2006 Steven Toth + * Copyright (c) 2006 Steven Toth * * 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 diff --git a/drivers/media/video/cx23885/cx23885-i2c.c b/drivers/media/video/cx23885/cx23885-i2c.c index c6bb0a0..f98e476 100644 --- a/drivers/media/video/cx23885/cx23885-i2c.c +++ b/drivers/media/video/cx23885/cx23885-i2c.c @@ -1,7 +1,7 @@ /* * Driver for the Conexant CX23885 PCIe bridge * - * Copyright (c) 2006 Steven Toth + * Copyright (c) 2006 Steven Toth * * 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 diff --git a/drivers/media/video/cx23885/cx23885-reg.h b/drivers/media/video/cx23885/cx23885-reg.h index bdd11bc..20b68a2 100644 --- a/drivers/media/video/cx23885/cx23885-reg.h +++ b/drivers/media/video/cx23885/cx23885-reg.h @@ -1,7 +1,7 @@ /* * Driver for the Conexant CX23885 PCIe bridge * - * Copyright (c) 2006 Steven Toth + * Copyright (c) 2006 Steven Toth * * 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 diff --git a/drivers/media/video/cx23885/cx23885-vbi.c b/drivers/media/video/cx23885/cx23885-vbi.c index e36e3fc..35e61cd 100644 --- a/drivers/media/video/cx23885/cx23885-vbi.c +++ b/drivers/media/video/cx23885/cx23885-vbi.c @@ -1,7 +1,7 @@ /* * Driver for the Conexant CX23885 PCIe bridge * - * Copyright (c) 2007 Steven Toth + * Copyright (c) 2007 Steven Toth * * 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 diff --git a/drivers/media/video/cx23885/cx23885-video.c b/drivers/media/video/cx23885/cx23885-video.c index ad2235d..6047c78 100644 --- a/drivers/media/video/cx23885/cx23885-video.c +++ b/drivers/media/video/cx23885/cx23885-video.c @@ -1,7 +1,7 @@ /* * Driver for the Conexant CX23885 PCIe bridge * - * Copyright (c) 2007 Steven Toth + * Copyright (c) 2007 Steven Toth * * 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 @@ -41,7 +41,7 @@ #endif MODULE_DESCRIPTION("v4l2 driver module for cx23885 based TV cards"); -MODULE_AUTHOR("Steven Toth "); +MODULE_AUTHOR("Steven Toth "); MODULE_LICENSE("GPL"); /* ------------------------------------------------------------------ */ diff --git a/drivers/media/video/cx23885/cx23885.h b/drivers/media/video/cx23885/cx23885.h index 00dfdc8..e23d97c 100644 --- a/drivers/media/video/cx23885/cx23885.h +++ b/drivers/media/video/cx23885/cx23885.h @@ -1,7 +1,7 @@ /* * Driver for the Conexant CX23885 PCIe bridge * - * Copyright (c) 2006 Steven Toth + * Copyright (c) 2006 Steven Toth * * 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 diff --git a/drivers/media/video/cx25840/cx25840-core.c b/drivers/media/video/cx25840/cx25840-core.c index 209d3bc..4da8cd7 100644 --- a/drivers/media/video/cx25840/cx25840-core.c +++ b/drivers/media/video/cx25840/cx25840-core.c @@ -13,7 +13,7 @@ * NTSC sliced VBI support by Christopher Neufeld * with additional fixes by Hans Verkuil . * - * CX23885 support by Steven Toth . + * CX23885 support by Steven Toth . * * This program is free software; you can redistribute it and/or * modify it under the terms of the GNU General Public License -- cgit v0.10.2 From d6db35e89c420d867e9ffdf145ecf2cb1b91291b Mon Sep 17 00:00:00 2001 From: Hans de Goede Date: Wed, 3 Sep 2008 17:12:13 -0300 Subject: V4L/DVB (8809): gspca: Revert commit 9a9335776548d01525141c6e8f0c12e86bbde982 the previous patch (sensor upside down). Signed-off-by: Hans de Goede Signed-off-by: Jean-Francois Moine Signed-off-by: Mauro Carvalho Chehab diff --git a/drivers/media/video/gspca/gspca.c b/drivers/media/video/gspca/gspca.c index 0b292ca..bffddf52 100644 --- a/drivers/media/video/gspca/gspca.c +++ b/drivers/media/video/gspca/gspca.c @@ -851,8 +851,6 @@ static int vidioc_querycap(struct file *file, void *priv, cap->capabilities = V4L2_CAP_VIDEO_CAPTURE | V4L2_CAP_STREAMING | V4L2_CAP_READWRITE; - if (gspca_dev->flags & GSPCA_SENSOR_UPSIDE_DOWN_FLAG) - cap->capabilities |= V4L2_CAP_SENSOR_UPSIDE_DOWN; return 0; } diff --git a/drivers/media/video/gspca/gspca.h b/drivers/media/video/gspca/gspca.h index 1920c99..2596568 100644 --- a/drivers/media/video/gspca/gspca.h +++ b/drivers/media/video/gspca/gspca.h @@ -118,9 +118,6 @@ struct gspca_frame { struct v4l2_buffer v4l2_buf; }; -/* defines for the flags member */ -#define GSPCA_SENSOR_UPSIDE_DOWN_FLAG 0x01 - struct gspca_dev { struct video_device vdev; /* !! must be the first item */ struct file_operations fops; @@ -166,7 +163,6 @@ struct gspca_dev { char nurbs; /* number of allocated URBs */ char memory; /* memory type (V4L2_MEMORY_xxx) */ __u8 nbalt; /* number of USB alternate settings */ - __u8 flags; /* see GSPCA_XXX_FLAG defines */ }; int gspca_dev_probe(struct usb_interface *intf, diff --git a/drivers/media/video/gspca/zc3xx.c b/drivers/media/video/gspca/zc3xx.c index f1d8c7a..79436f2 100644 --- a/drivers/media/video/gspca/zc3xx.c +++ b/drivers/media/video/gspca/zc3xx.c @@ -70,10 +70,6 @@ struct sd { unsigned short chip_revision; }; -#define DRIVER_INFO(sensor, flags) .driver_info = ((sensor) << 8) | (flags) -#define DRIVER_INFO_GET_SENSOR(driver_info) ((driver_info) >> 8) -#define DRIVER_INFO_GET_FLAGS(driver_info) ((driver_info) & 0xff) - /* V4L2 controls supported by the driver */ static int sd_setbrightness(struct gspca_dev *gspca_dev, __s32 val); static int sd_getbrightness(struct gspca_dev *gspca_dev, __s32 *val); @@ -7019,8 +7015,7 @@ static int sd_config(struct gspca_dev *gspca_dev, /* define some sensors from the vendor/product */ sd->sharpness = 2; - sd->sensor = DRIVER_INFO_GET_SENSOR(id->driver_info); - gspca_dev->flags = DRIVER_INFO_GET_FLAGS(id->driver_info); + sd->sensor = id->driver_info; sensor = zcxx_probeSensor(gspca_dev); if (sensor >= 0) PDEBUG(D_PROBE, "probe sensor -> %02x", sensor); @@ -7510,19 +7505,19 @@ static const __devinitdata struct usb_device_id device_table[] = { {USB_DEVICE(0x041e, 0x041e)}, #ifndef CONFIG_USB_ZC0301 {USB_DEVICE(0x041e, 0x4017)}, - {USB_DEVICE(0x041e, 0x401c), DRIVER_INFO(SENSOR_PAS106, 0)}, + {USB_DEVICE(0x041e, 0x401c), .driver_info = SENSOR_PAS106}, {USB_DEVICE(0x041e, 0x401e)}, {USB_DEVICE(0x041e, 0x401f)}, #endif {USB_DEVICE(0x041e, 0x4029)}, #ifndef CONFIG_USB_ZC0301 - {USB_DEVICE(0x041e, 0x4034), DRIVER_INFO(SENSOR_PAS106, 0)}, - {USB_DEVICE(0x041e, 0x4035), DRIVER_INFO(SENSOR_PAS106, 0)}, + {USB_DEVICE(0x041e, 0x4034), .driver_info = SENSOR_PAS106}, + {USB_DEVICE(0x041e, 0x4035), .driver_info = SENSOR_PAS106}, {USB_DEVICE(0x041e, 0x4036)}, {USB_DEVICE(0x041e, 0x403a)}, #endif - {USB_DEVICE(0x041e, 0x4051), DRIVER_INFO(SENSOR_TAS5130C_VF0250, 0)}, - {USB_DEVICE(0x041e, 0x4053), DRIVER_INFO(SENSOR_TAS5130C_VF0250, 0)}, + {USB_DEVICE(0x041e, 0x4051), .driver_info = SENSOR_TAS5130C_VF0250}, + {USB_DEVICE(0x041e, 0x4053), .driver_info = SENSOR_TAS5130C_VF0250}, #ifndef CONFIG_USB_ZC0301 {USB_DEVICE(0x0458, 0x7007)}, {USB_DEVICE(0x0458, 0x700c)}, @@ -7548,13 +7543,11 @@ static const __devinitdata struct usb_device_id device_table[] = { {USB_DEVICE(0x046d, 0x08d9)}, {USB_DEVICE(0x046d, 0x08d8)}, {USB_DEVICE(0x046d, 0x08da)}, - {USB_DEVICE(0x046d, 0x08dd), DRIVER_INFO(SENSOR_MC501CB, 0)}, - {USB_DEVICE(0x0471, 0x0325), DRIVER_INFO(SENSOR_PAS106, - GSPCA_SENSOR_UPSIDE_DOWN_FLAG)}, - {USB_DEVICE(0x0471, 0x0326), DRIVER_INFO(SENSOR_PAS106, - GSPCA_SENSOR_UPSIDE_DOWN_FLAG)}, - {USB_DEVICE(0x0471, 0x032d), DRIVER_INFO(SENSOR_PAS106, 0)}, - {USB_DEVICE(0x0471, 0x032e), DRIVER_INFO(SENSOR_PAS106, 0)}, + {USB_DEVICE(0x046d, 0x08dd), .driver_info = SENSOR_MC501CB}, + {USB_DEVICE(0x0471, 0x0325), .driver_info = SENSOR_PAS106}, + {USB_DEVICE(0x0471, 0x0326), .driver_info = SENSOR_PAS106}, + {USB_DEVICE(0x0471, 0x032d), .driver_info = SENSOR_PAS106}, + {USB_DEVICE(0x0471, 0x032e), .driver_info = SENSOR_PAS106}, {USB_DEVICE(0x055f, 0xc005)}, #ifndef CONFIG_USB_ZC0301 {USB_DEVICE(0x055f, 0xd003)}, @@ -7566,7 +7559,7 @@ static const __devinitdata struct usb_device_id device_table[] = { {USB_DEVICE(0x0ac8, 0x301b)}, {USB_DEVICE(0x0ac8, 0x303b)}, #endif - {USB_DEVICE(0x0ac8, 0x305b), DRIVER_INFO(SENSOR_TAS5130C_VF0250, 0)}, + {USB_DEVICE(0x0ac8, 0x305b), .driver_info = SENSOR_TAS5130C_VF0250}, #ifndef CONFIG_USB_ZC0301 {USB_DEVICE(0x0ac8, 0x307b)}, {USB_DEVICE(0x10fd, 0x0128)}, diff --git a/include/linux/videodev2.h b/include/linux/videodev2.h index 4c30655..6c73516 100644 --- a/include/linux/videodev2.h +++ b/include/linux/videodev2.h @@ -261,11 +261,6 @@ struct v4l2_capability { #define V4L2_CAP_ASYNCIO 0x02000000 /* async I/O */ #define V4L2_CAP_STREAMING 0x04000000 /* streaming I/O ioctls */ -/* This flags gets set if the "sensor" is known to be upside down and this can - *not* be fixed using v4l2 flipx/y controls. Note that absence of this flag - is not a guarantee for the image not being upside down. */ -#define V4L2_CAP_SENSOR_UPSIDE_DOWN 0x10000000 - /* * V I D E O I M A G E F O R M A T */ -- cgit v0.10.2 From 62ee8eeebd1bf6c29977800ac18dfcecf584d42e Mon Sep 17 00:00:00 2001 From: Jean-Francois Moine Date: Wed, 3 Sep 2008 17:12:13 -0300 Subject: V4L/DVB (8810): gspca: Compile error when CONFIG_PM not defined. Signed-off-by: Jean-Francois Moine Signed-off-by: Mauro Carvalho Chehab diff --git a/drivers/media/video/gspca/gspca.c b/drivers/media/video/gspca/gspca.c index bffddf52..28842ed 100644 --- a/drivers/media/video/gspca/gspca.c +++ b/drivers/media/video/gspca/gspca.c @@ -114,7 +114,9 @@ static void fill_frame(struct gspca_dev *gspca_dev, cam_pkt_op pkt_scan; if (urb->status != 0) { +#ifdef CONFIG_PM if (!gspca_dev->frozen) +#endif PDEBUG(D_ERR|D_PACK, "urb status: %d", urb->status); return; /* disconnection ? */ } -- cgit v0.10.2 From 327c4abf74a4426676df6c359b2a3dea2a5d126e Mon Sep 17 00:00:00 2001 From: Hans de Goede Date: Wed, 3 Sep 2008 17:12:14 -0300 Subject: V4L/DVB (8812): gspca: Do pac73xx webcams work. - documentation for some registers - some preparations for adding autogain_n_exposure functionality - various pac7311 fixes - disable brightness and colors controls for 7311 - fix contrast control for 7311 - add hflip and vflip controls for 7311 - minimal jpeg header - proper SOF detection Signed-off-by: Hans de Goede Signed-off-by: Jean-Francois Moine Signed-off-by: Mauro Carvalho Chehab diff --git a/drivers/media/video/gspca/pac207.c b/drivers/media/video/gspca/pac207.c index d9668f4..620c963 100644 --- a/drivers/media/video/gspca/pac207.c +++ b/drivers/media/video/gspca/pac207.c @@ -181,9 +181,6 @@ static const __u8 pac207_sensor_init[][8] = { /* 48 reg_72 Rate Control end BalSize_4a =0x36 */ static const __u8 PacReg72[] = { 0x00, 0x00, 0x36, 0x00 }; -static const unsigned char pac207_sof_marker[5] = - { 0xff, 0xff, 0x00, 0xff, 0x96 }; - static int pac207_write_regs(struct gspca_dev *gspca_dev, u16 index, const u8 *buffer, u16 length) { @@ -367,31 +364,8 @@ static void pac207_do_auto_gain(struct gspca_dev *gspca_dev) sd->autogain_ignore_frames = PAC207_AUTOGAIN_IGNORE_FRAMES; } -static unsigned char *pac207_find_sof(struct gspca_dev *gspca_dev, - unsigned char *m, int len) -{ - struct sd *sd = (struct sd *) gspca_dev; - int i; - - /* Search for the SOF marker (fixed part) in the header */ - for (i = 0; i < len; i++) { - if (m[i] == pac207_sof_marker[sd->sof_read]) { - sd->sof_read++; - if (sd->sof_read == sizeof(pac207_sof_marker)) { - PDEBUG(D_STREAM, - "SOF found, bytes to analyze: %u." - " Frame starts at byte #%u", - len, i + 1); - sd->sof_read = 0; - return m + i + 1; - } - } else { - sd->sof_read = 0; - } - } - - return NULL; -} +/* Include pac common sof detection functions */ +#include "pac_common.h" static void sd_pkt_scan(struct gspca_dev *gspca_dev, struct gspca_frame *frame, @@ -401,14 +375,14 @@ static void sd_pkt_scan(struct gspca_dev *gspca_dev, struct sd *sd = (struct sd *) gspca_dev; unsigned char *sof; - sof = pac207_find_sof(gspca_dev, data, len); + sof = pac_find_sof(gspca_dev, data, len); if (sof) { int n; /* finish decoding current frame */ n = sof - data; - if (n > sizeof pac207_sof_marker) - n -= sizeof pac207_sof_marker; + if (n > sizeof pac_sof_marker) + n -= sizeof pac_sof_marker; else n = 0; frame = gspca_frame_add(gspca_dev, LAST_PACKET, frame, diff --git a/drivers/media/video/gspca/pac7311.c b/drivers/media/video/gspca/pac7311.c index 4cc9379..bed04cc 100644 --- a/drivers/media/video/gspca/pac7311.c +++ b/drivers/media/video/gspca/pac7311.c @@ -19,10 +19,36 @@ * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA */ +/* Some documentation about various registers as determined by trial and error. + When the register addresses differ between the 7202 and the 7311 the 2 + different addresses are written as 7302addr/7311addr, when one of the 2 + addresses is a - sign that register description is not valid for the + matching IC. + + Register page 1: + + Address Description + -/0x08 Unknown compressor related, must always be 8 except when not + in 640x480 resolution and page 4 reg 2 <= 3 then set it to 9 ! + -/0x1b Auto white balance related, bit 0 is AWB enable (inverted) + bits 345 seem to toggle per color gains on/off (inverted) + 0x78 Global control, bit 6 controls the LED (inverted) + -/0x80 JPEG compression ratio ? Best not touched + + Register page 3/4: + + Address Description + 0x02 Clock divider 2-63, fps =~ 60 / val. Must be a multiple of 3 on + the 7302, so one of 3, 6, 9, ... + -/0x0f Master gain 1-245, low value = high gain + 0x10/- Master gain 0-31 + -/0x10 Another gain 0-15, limited influence (1-2x gain I guess) + 0x21 Bitfield: 0-1 unused, 2-3 vflip/hflip, 4-5 unknown, 6-7 unused +*/ + #define MODULE_NAME "pac7311" #include "gspca.h" -#include "jpeg.h" MODULE_AUTHOR("Thomas Kaiser thomas@kaiser-linux.li"); MODULE_DESCRIPTION("Pixart PAC7311"); @@ -32,25 +58,22 @@ MODULE_LICENSE("GPL"); struct sd { struct gspca_dev gspca_dev; /* !! must be the first item */ - int lum_sum; - atomic_t avg_lum; - atomic_t do_gain; - unsigned char brightness; unsigned char contrast; unsigned char colors; unsigned char autogain; __u8 hflip; __u8 vflip; - __u8 qindex; - - char tosof; /* number of bytes before next start of frame */ - signed char ag_cnt; -#define AG_CNT_START 13 __u8 sensor; #define SENSOR_PAC7302 0 #define SENSOR_PAC7311 1 + + u8 sof_read; + u8 header_read; + u8 autogain_ignore_frames; + + atomic_t avg_lum; }; /* V4L2 controls supported by the driver */ @@ -92,7 +115,7 @@ static struct ctrl sd_ctrls[] = { #define CONTRAST_MAX 255 .maximum = CONTRAST_MAX, .step = 1, -#define CONTRAST_DEF 60 +#define CONTRAST_DEF 127 .default_value = CONTRAST_DEF, }, .set = sd_setcontrast, @@ -243,7 +266,7 @@ static const __u8 start_7302[] = { 0x2a, 5, 0xc8, 0x00, 0x18, 0x12, 0x22, 0x64, 8, 0x00, 0x00, 0xf0, 0x01, 0x14, 0x44, 0x44, 0x44, 0x6e, 1, 0x08, - 0xff, 1, 0x03, /* page 1 */ + 0xff, 1, 0x01, /* page 1 */ 0x78, 1, 0x00, 0, 0 /* end of sequence */ }; @@ -274,9 +297,9 @@ static const __u8 page3_7302[] = { /* pac 7311 */ static const __u8 probe_7311[] = { - 0x78, 0x40, /* Bit_0=start stream, Bit_7=LED */ - 0x78, 0x40, /* Bit_0=start stream, Bit_7=LED */ - 0x78, 0x44, /* Bit_0=start stream, Bit_7=LED */ + 0x78, 0x40, /* Bit_0=start stream, Bit_6=LED */ + 0x78, 0x40, /* Bit_0=start stream, Bit_6=LED */ + 0x78, 0x44, /* Bit_0=start stream, Bit_6=LED */ 0xff, 0x04, 0x27, 0x80, 0x28, 0xca, @@ -340,18 +363,6 @@ static void reg_w_buf(struct gspca_dev *gspca_dev, 500); } -static __u8 reg_r(struct gspca_dev *gspca_dev, - __u8 index) -{ - usb_control_msg(gspca_dev->dev, - usb_rcvctrlpipe(gspca_dev->dev, 0), - 0, /* request */ - USB_DIR_IN | USB_TYPE_VENDOR | USB_RECIP_DEVICE, - 0, /* value */ - index, gspca_dev->usb_buf, 1, - 500); - return gspca_dev->usb_buf[0]; -} static void reg_w(struct gspca_dev *gspca_dev, __u8 index, @@ -413,7 +424,7 @@ static void reg_w_var(struct gspca_dev *gspca_dev, reg_w_page(gspca_dev, page3_7302, sizeof page3_7302); break; default: - if (len > 32) { + if (len > 64) { PDEBUG(D_ERR|D_STREAM, "Incorrect variable sequence"); return; @@ -453,7 +464,7 @@ static int sd_config(struct gspca_dev *gspca_dev, cam->nmodes = 1; } else { PDEBUG(D_CONF, "Find Sensor PAC7311"); - reg_w_seq(gspca_dev, probe_7302, sizeof probe_7302); + reg_w_seq(gspca_dev, probe_7311, sizeof probe_7311); cam->cam_mode = vga_mode; cam->nmodes = ARRAY_SIZE(vga_mode); @@ -465,8 +476,6 @@ static int sd_config(struct gspca_dev *gspca_dev, sd->autogain = AUTOGAIN_DEF; sd->hflip = HFLIP_DEF; sd->vflip = VFLIP_DEF; - sd->qindex = 3; - sd->ag_cnt = -1; return 0; } @@ -497,6 +506,7 @@ static void setbrightcont(struct gspca_dev *gspca_dev) reg_w(gspca_dev, 0xdc, 0x01); } +/* This function is used by pac7302 only */ static void setbrightness(struct gspca_dev *gspca_dev) { struct sd *sd = (struct sd *) gspca_dev; @@ -506,7 +516,10 @@ static void setbrightness(struct gspca_dev *gspca_dev) setbrightcont(gspca_dev); return; } -/*jfm: inverted?*/ +/* HDG: this is not brightness but gain, I'll add gain and exposure controls + in a next patch */ + return; + brightness = BRIGHTNESS_MAX - sd->brightness; reg_w(gspca_dev, 0xff, 0x04); reg_w(gspca_dev, 0x0e, 0x00); @@ -524,12 +537,13 @@ static void setcontrast(struct gspca_dev *gspca_dev) setbrightcont(gspca_dev); return; } - reg_w(gspca_dev, 0xff, 0x01); - reg_w(gspca_dev, 0x10, sd->contrast); + reg_w(gspca_dev, 0xff, 0x04); + reg_w(gspca_dev, 0x10, sd->contrast >> 4); /* load registers to sensor (Bit 0, auto clear) */ reg_w(gspca_dev, 0x11, 0x01); } +/* This function is used by pac7302 only */ static void setcolors(struct gspca_dev *gspca_dev) { struct sd *sd = (struct sd *) gspca_dev; @@ -551,36 +565,24 @@ static void setcolors(struct gspca_dev *gspca_dev) reg_w(gspca_dev, 0x0f + 2 * i + 1, v); } reg_w(gspca_dev, 0xdc, 0x01); - return; + PDEBUG(D_CONF|D_STREAM, "color: %i", sd->colors); } - reg_w(gspca_dev, 0xff, 0x01); - reg_w(gspca_dev, 0x80, sd->colors); - /* load registers to sensor (Bit 0, auto clear) */ - reg_w(gspca_dev, 0x11, 0x01); - PDEBUG(D_CONF|D_STREAM, "color: %i", sd->colors); } -static void setautogain(struct gspca_dev *gspca_dev) -{ - struct sd *sd = (struct sd *) gspca_dev; - - if (sd->autogain) { - sd->lum_sum = 0; - sd->ag_cnt = AG_CNT_START; - } else { - sd->ag_cnt = -1; - } -} - -/* this function is used by pac7302 only */ static void sethvflip(struct gspca_dev *gspca_dev) { struct sd *sd = (struct sd *) gspca_dev; __u8 data; - reg_w(gspca_dev, 0xff, 0x03); /* page 3 */ - data = (sd->hflip ? 0x00 : 0x08) - | (sd->vflip ? 0x04 : 0x00); + if (sd->sensor == SENSOR_PAC7302) { + reg_w(gspca_dev, 0xff, 0x03); /* page 3 */ + data = (sd->hflip ? 0x00 : 0x08) + | (sd->vflip ? 0x04 : 0x00); + } else { + reg_w(gspca_dev, 0xff, 0x04); /* page 3 */ + data = (sd->hflip ? 0x04 : 0x00) + | (sd->vflip ? 0x08 : 0x00); + } reg_w(gspca_dev, 0x21, data); reg_w(gspca_dev, 0x11, 0x01); } @@ -588,7 +590,6 @@ static void sethvflip(struct gspca_dev *gspca_dev) /* this function is called at open time */ static int sd_open(struct gspca_dev *gspca_dev) { - reg_w(gspca_dev, 0x78, 0x44); /* Turn on LED */ return 0; } @@ -596,7 +597,7 @@ static void sd_start(struct gspca_dev *gspca_dev) { struct sd *sd = (struct sd *) gspca_dev; - sd->tosof = 0; + sd->sof_read = 0; if (sd->sensor == SENSOR_PAC7302) reg_w_var(gspca_dev, start_7302); @@ -606,7 +607,6 @@ static void sd_start(struct gspca_dev *gspca_dev) setcontrast(gspca_dev); setbrightness(gspca_dev); setcolors(gspca_dev); - setautogain(gspca_dev); /* set correct resolution */ switch (gspca_dev->cam.cam_mode[(int) gspca_dev->curr_mode].priv) { @@ -621,7 +621,7 @@ static void sd_start(struct gspca_dev *gspca_dev) break; case 1: /* 320x240 pac7311 */ reg_w(gspca_dev, 0xff, 0x04); - reg_w(gspca_dev, 0x02, 0x07); + reg_w(gspca_dev, 0x02, 0x03); reg_w(gspca_dev, 0xff, 0x01); reg_w(gspca_dev, 0x08, 0x09); reg_w(gspca_dev, 0x17, 0x30); @@ -650,6 +650,10 @@ static void sd_start(struct gspca_dev *gspca_dev) reg_w(gspca_dev, 0x78, 0x44); reg_w(gspca_dev, 0x78, 0x45); } + + sd->sof_read = 0; + sd->autogain_ignore_frames = 0; + atomic_set(&sd->avg_lum, -1); } static void sd_stopN(struct gspca_dev *gspca_dev) @@ -657,6 +661,7 @@ static void sd_stopN(struct gspca_dev *gspca_dev) struct sd *sd = (struct sd *) gspca_dev; if (sd->sensor == SENSOR_PAC7302) { + reg_w(gspca_dev, 0xff, 0x01); reg_w(gspca_dev, 0x78, 0x00); reg_w(gspca_dev, 0x78, 0x00); return; @@ -668,9 +673,9 @@ static void sd_stopN(struct gspca_dev *gspca_dev) reg_w(gspca_dev, 0x2a, 0x0e); reg_w(gspca_dev, 0xff, 0x01); reg_w(gspca_dev, 0x3e, 0x20); - reg_w(gspca_dev, 0x78, 0x44); /* Bit_0=start stream, Bit_7=LED */ - reg_w(gspca_dev, 0x78, 0x44); /* Bit_0=start stream, Bit_7=LED */ - reg_w(gspca_dev, 0x78, 0x44); /* Bit_0=start stream, Bit_7=LED */ + reg_w(gspca_dev, 0x78, 0x44); /* Bit_0=start stream, Bit_6=LED */ + reg_w(gspca_dev, 0x78, 0x44); /* Bit_0=start stream, Bit_6=LED */ + reg_w(gspca_dev, 0x78, 0x44); /* Bit_0=start stream, Bit_6=LED */ } static void sd_stop0(struct gspca_dev *gspca_dev) @@ -690,42 +695,22 @@ static void sd_close(struct gspca_dev *gspca_dev) static void do_autogain(struct gspca_dev *gspca_dev) { - struct sd *sd = (struct sd *) gspca_dev; - int luma; - int luma_mean = 128; - int luma_delta = 20; - __u8 spring = 5; - int Gbright; - - if (!atomic_read(&sd->do_gain)) - return; - atomic_set(&sd->do_gain, 0); - - luma = atomic_read(&sd->avg_lum); - Gbright = reg_r(gspca_dev, 0x02); - PDEBUG(D_FRAM, "luma mean %d", luma); - if (luma < luma_mean - luma_delta || - luma > luma_mean + luma_delta) { - Gbright += (luma_mean - luma) >> spring; - if (Gbright > 0x1a) - Gbright = 0x1a; - else if (Gbright < 4) - Gbright = 4; - PDEBUG(D_FRAM, "gbright %d", Gbright); - if (sd->sensor == SENSOR_PAC7302) { - reg_w(gspca_dev, 0xff, 0x03); - reg_w(gspca_dev, 0x10, Gbright); - /* load registers to sensor (Bit 0, auto clear) */ - reg_w(gspca_dev, 0x11, 0x01); - } else { - reg_w(gspca_dev, 0xff, 0x04); - reg_w(gspca_dev, 0x0f, Gbright); - /* load registers to sensor (Bit 0, auto clear) */ - reg_w(gspca_dev, 0x11, 0x01); - } - } } +static const unsigned char pac7311_jpeg_header1[] = { + 0xff, 0xd8, 0xff, 0xc0, 0x00, 0x11, 0x08 +}; + +static const unsigned char pac7311_jpeg_header2[] = { + 0x03, 0x01, 0x21, 0x00, 0x02, 0x11, 0x01, 0x03, 0x11, 0x01, 0xff, 0xda, + 0x00, 0x0c, 0x03, 0x01, 0x00, 0x02, 0x11, 0x03, 0x11, 0x00, 0x3f, 0x00 +}; + +/* Include pac common sof detection functions */ +#include "pac_common.h" + +#define HEADER_LENGTH 2 + /* this function is run at interrupt level */ static void sd_pkt_scan(struct gspca_dev *gspca_dev, struct gspca_frame *frame, /* target */ @@ -733,58 +718,89 @@ static void sd_pkt_scan(struct gspca_dev *gspca_dev, int len) /* iso packet length */ { struct sd *sd = (struct sd *) gspca_dev; - int i; - -#define INTER_FRAME 0x53 /* eof + inter frame + sof */ -#define LUM_OFFSET 0x1e /* reverse offset / start of frame */ - - /* - * inside a frame, there may be: - * escaped ff ('ff 00') - * sequences'ff ff ff xx' to remove - * end of frame ('ff d9') - * at the end of frame, there are: - * ff d9 end of frame - * 0x33 bytes - * one byte luminosity - * 0x16 bytes - * ff ff 00 ff 96 62 44 start of frame - */ - - if (sd->tosof != 0) { /* if outside a frame */ - - /* get the luminosity and go to the start of frame */ - data += sd->tosof; - len -= sd->tosof; - if (sd->tosof > LUM_OFFSET) - sd->lum_sum += data[-LUM_OFFSET]; - sd->tosof = 0; - jpeg_put_header(gspca_dev, frame, sd->qindex, 0x21); + unsigned char *sof; + + sof = pac_find_sof(gspca_dev, data, len); + if (sof) { + unsigned char tmpbuf[4]; + int n, lum_offset, footer_length; + + if (sd->sensor == SENSOR_PAC7302) { + lum_offset = 34 + sizeof pac_sof_marker; + footer_length = 74; + } else { + lum_offset = 24 + sizeof pac_sof_marker; + footer_length = 26; + } + + /* Finish decoding current frame */ + n = (sof - data) - (footer_length + sizeof pac_sof_marker); + if (n < 0) { + frame->data_end += n; + n = 0; + } + frame = gspca_frame_add(gspca_dev, INTER_PACKET, frame, + data, n); + if (gspca_dev->last_packet_type != DISCARD_PACKET && + frame->data_end[-2] == 0xff && + frame->data_end[-1] == 0xd9) + frame = gspca_frame_add(gspca_dev, LAST_PACKET, frame, + NULL, 0); + + n = sof - data; + len -= n; + data = sof; + + /* Get average lumination */ + if (gspca_dev->last_packet_type == LAST_PACKET && + n >= lum_offset) { + if (sd->sensor == SENSOR_PAC7302) + atomic_set(&sd->avg_lum, + (data[-lum_offset] << 8) | + data[-lum_offset + 1]); + else + atomic_set(&sd->avg_lum, + data[-lum_offset] + + data[-lum_offset + 1]); + } else { + atomic_set(&sd->avg_lum, -1); + } + + /* Start the new frame with the jpeg header */ + gspca_frame_add(gspca_dev, FIRST_PACKET, frame, + pac7311_jpeg_header1, sizeof(pac7311_jpeg_header1)); + if (sd->sensor == SENSOR_PAC7302) { + /* The PAC7302 has the image rotated 90 degrees */ + tmpbuf[0] = gspca_dev->width >> 8; + tmpbuf[1] = gspca_dev->width & 0xff; + tmpbuf[2] = gspca_dev->height >> 8; + tmpbuf[3] = gspca_dev->height & 0xff; + } else { + tmpbuf[0] = gspca_dev->height >> 8; + tmpbuf[1] = gspca_dev->height & 0xff; + tmpbuf[2] = gspca_dev->width >> 8; + tmpbuf[3] = gspca_dev->width & 0xff; + } + gspca_frame_add(gspca_dev, INTER_PACKET, frame, tmpbuf, 4); + gspca_frame_add(gspca_dev, INTER_PACKET, frame, + pac7311_jpeg_header2, sizeof(pac7311_jpeg_header2)); + + sd->header_read = 0; } - for (i = 0; i < len; i++) { - if (data[i] != 0xff) - continue; - switch (data[i + 1]) { - case 0xd9: /* 'ff d9' end of frame */ - frame = gspca_frame_add(gspca_dev, - LAST_PACKET, - frame, data, i + 2); - data += i + INTER_FRAME; - len -= i + INTER_FRAME; - i = 0; - if (len > -LUM_OFFSET) - sd->lum_sum += data[-LUM_OFFSET]; - if (len < 0) { - sd->tosof = -len; - break; - } - jpeg_put_header(gspca_dev, frame, sd->qindex, 0x21); - break; + if (sd->header_read < HEADER_LENGTH) { + /* skip the variable part of the sof header */ + int needed = HEADER_LENGTH - sd->header_read; + if (len <= needed) { + sd->header_read += len; + return; } + data += needed; + len -= needed; + sd->header_read = HEADER_LENGTH; } - gspca_frame_add(gspca_dev, INTER_PACKET, - frame, data, i); + + gspca_frame_add(gspca_dev, INTER_PACKET, frame, data, len); } static int sd_setbrightness(struct gspca_dev *gspca_dev, __s32 val) @@ -846,8 +862,7 @@ static int sd_setautogain(struct gspca_dev *gspca_dev, __s32 val) struct sd *sd = (struct sd *) gspca_dev; sd->autogain = val; - if (gspca_dev->streaming) - setautogain(gspca_dev); + return 0; } diff --git a/drivers/media/video/gspca/pac_common.h b/drivers/media/video/gspca/pac_common.h new file mode 100644 index 0000000..a19b5d4 --- /dev/null +++ b/drivers/media/video/gspca/pac_common.h @@ -0,0 +1,53 @@ +/* + * Pixart PAC207BCA / PAC73xx common functions + * + * Copyright (C) 2008 Hans de Goede + * Copyright (C) 2005 Thomas Kaiser thomas@kaiser-linux.li + * Copyleft (C) 2005 Michel Xhaard mxhaard@magic.fr + * + * V4L2 by Jean-Francois Moine + * + * 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 + * (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 + * + */ + +static const unsigned char pac_sof_marker[5] = + { 0xff, 0xff, 0x00, 0xff, 0x96 }; + +static unsigned char *pac_find_sof(struct gspca_dev *gspca_dev, + unsigned char *m, int len) +{ + struct sd *sd = (struct sd *) gspca_dev; + int i; + + /* Search for the SOF marker (fixed part) in the header */ + for (i = 0; i < len; i++) { + if (m[i] == pac_sof_marker[sd->sof_read]) { + sd->sof_read++; + if (sd->sof_read == sizeof(pac_sof_marker)) { + PDEBUG(D_STREAM, + "SOF found, bytes to analyze: %u." + " Frame starts at byte #%u", + len, i + 1); + sd->sof_read = 0; + return m + i + 1; + } + } else { + sd->sof_read = 0; + } + } + + return NULL; +} -- cgit v0.10.2 From 221e7dbe55fe515ff786142bac64b507fa9f26de Mon Sep 17 00:00:00 2001 From: Hans de Goede Date: Wed, 3 Sep 2008 17:12:14 -0300 Subject: V4L/DVB (8813): gspca: Adjust SOF detection for pac73xx. Signed-off-by: Hans de Goede Signed-off-by: Jean-Francois Moine Signed-off-by: Mauro Carvalho Chehab diff --git a/drivers/media/video/gspca/pac7311.c b/drivers/media/video/gspca/pac7311.c index bed04cc..3c51428 100644 --- a/drivers/media/video/gspca/pac7311.c +++ b/drivers/media/video/gspca/pac7311.c @@ -70,7 +70,6 @@ struct sd { #define SENSOR_PAC7311 1 u8 sof_read; - u8 header_read; u8 autogain_ignore_frames; atomic_t avg_lum; @@ -709,8 +708,6 @@ static const unsigned char pac7311_jpeg_header2[] = { /* Include pac common sof detection functions */ #include "pac_common.h" -#define HEADER_LENGTH 2 - /* this function is run at interrupt level */ static void sd_pkt_scan(struct gspca_dev *gspca_dev, struct gspca_frame *frame, /* target */ @@ -784,22 +781,7 @@ static void sd_pkt_scan(struct gspca_dev *gspca_dev, gspca_frame_add(gspca_dev, INTER_PACKET, frame, tmpbuf, 4); gspca_frame_add(gspca_dev, INTER_PACKET, frame, pac7311_jpeg_header2, sizeof(pac7311_jpeg_header2)); - - sd->header_read = 0; } - - if (sd->header_read < HEADER_LENGTH) { - /* skip the variable part of the sof header */ - int needed = HEADER_LENGTH - sd->header_read; - if (len <= needed) { - sd->header_read += len; - return; - } - data += needed; - len -= needed; - sd->header_read = HEADER_LENGTH; - } - gspca_frame_add(gspca_dev, INTER_PACKET, frame, data, len); } -- cgit v0.10.2 From f50ba1bed3cfd65d6899afc4cb77299ee5c297ae Mon Sep 17 00:00:00 2001 From: Jean-Francois Moine Date: Wed, 3 Sep 2008 17:12:14 -0300 Subject: V4L/DVB (8814): gspca: Set DISABLED the disabled controls at query control time. Signed-off-by: Jean-Francois Moine Signed-off-by: Mauro Carvalho Chehab diff --git a/drivers/media/video/gspca/etoms.c b/drivers/media/video/gspca/etoms.c index a3cccab..e5a9eee 100644 --- a/drivers/media/video/gspca/etoms.c +++ b/drivers/media/video/gspca/etoms.c @@ -81,6 +81,7 @@ static struct ctrl sd_ctrls[] = { .set = sd_setcontrast, .get = sd_getcontrast, }, +#define COLOR_IDX 2 { { .id = V4L2_CID_SATURATION, @@ -665,6 +666,7 @@ static int sd_config(struct gspca_dev *gspca_dev, } else { cam->cam_mode = vga_mode; cam->nmodes = sizeof vga_mode / sizeof vga_mode[0]; + gspca_dev->ctrl_dis = (1 << COLOR_IDX); } sd->brightness = BRIGHTNESS_DEF; sd->contrast = CONTRAST_DEF; diff --git a/drivers/media/video/gspca/gspca.c b/drivers/media/video/gspca/gspca.c index 28842ed..33161e1 100644 --- a/drivers/media/video/gspca/gspca.c +++ b/drivers/media/video/gspca/gspca.c @@ -856,37 +856,44 @@ static int vidioc_querycap(struct file *file, void *priv, return 0; } -/* the use of V4L2_CTRL_FLAG_NEXT_CTRL asks for the controls to be sorted */ static int vidioc_queryctrl(struct file *file, void *priv, struct v4l2_queryctrl *q_ctrl) { struct gspca_dev *gspca_dev = priv; - int i; + int i, ix; u32 id; + ix = -1; id = q_ctrl->id; if (id & V4L2_CTRL_FLAG_NEXT_CTRL) { id &= V4L2_CTRL_ID_MASK; id++; for (i = 0; i < gspca_dev->sd_desc->nctrls; i++) { - if (id >= gspca_dev->sd_desc->ctrls[i].qctrl.id) { - memcpy(q_ctrl, - &gspca_dev->sd_desc->ctrls[i].qctrl, - sizeof *q_ctrl); - return 0; + if (id < gspca_dev->sd_desc->ctrls[i].qctrl.id) + continue; + if (ix < 0) { + ix = i; + continue; } + if (gspca_dev->sd_desc->ctrls[i].qctrl.id + > gspca_dev->sd_desc->ctrls[ix].qctrl.id) + continue; + ix = i; } - return -EINVAL; } for (i = 0; i < gspca_dev->sd_desc->nctrls; i++) { if (id == gspca_dev->sd_desc->ctrls[i].qctrl.id) { - memcpy(q_ctrl, - &gspca_dev->sd_desc->ctrls[i].qctrl, - sizeof *q_ctrl); - return 0; + ix = i; + break; } } - return -EINVAL; + if (ix < 0) + return -EINVAL; + memcpy(q_ctrl, &gspca_dev->sd_desc->ctrls[ix].qctrl, + sizeof *q_ctrl); + if (gspca_dev->ctrl_dis & (1 << ix)) + q_ctrl->flags |= V4L2_CTRL_FLAG_DISABLED; + return 0; } static int vidioc_s_ctrl(struct file *file, void *priv, diff --git a/drivers/media/video/gspca/gspca.h b/drivers/media/video/gspca/gspca.h index 2596568..a804ef1 100644 --- a/drivers/media/video/gspca/gspca.h +++ b/drivers/media/video/gspca/gspca.h @@ -126,6 +126,7 @@ struct gspca_dev { struct cam cam; /* device information */ const struct sd_desc *sd_desc; /* subdriver description */ + unsigned ctrl_dis; /* disabled controls (bit map) */ __u8 usb_buf[8]; /* buffer for USB exchanges */ struct urb *urb[MAX_NURBS]; diff --git a/drivers/media/video/gspca/pac7311.c b/drivers/media/video/gspca/pac7311.c index 3c51428..69d6100 100644 --- a/drivers/media/video/gspca/pac7311.c +++ b/drivers/media/video/gspca/pac7311.c @@ -150,6 +150,7 @@ static struct ctrl sd_ctrls[] = { .get = sd_getautogain, }, /* next controls work with pac7302 only */ +#define HFLIP_IDX 4 { { .id = V4L2_CID_HFLIP, @@ -164,6 +165,7 @@ static struct ctrl sd_ctrls[] = { .set = sd_sethflip, .get = sd_gethflip, }, +#define VFLIP_IDX 5 { { .id = V4L2_CID_VFLIP, @@ -467,6 +469,8 @@ static int sd_config(struct gspca_dev *gspca_dev, cam->cam_mode = vga_mode; cam->nmodes = ARRAY_SIZE(vga_mode); + gspca_dev->ctrl_dis = (1 << HFLIP_IDX) + | (1 << VFLIP_IDX); } sd->brightness = BRIGHTNESS_DEF; diff --git a/drivers/media/video/gspca/sonixj.c b/drivers/media/video/gspca/sonixj.c index 0d46776..e657b8b 100644 --- a/drivers/media/video/gspca/sonixj.c +++ b/drivers/media/video/gspca/sonixj.c @@ -116,6 +116,7 @@ static struct ctrl sd_ctrls[] = { .set = sd_setcolors, .get = sd_getcolors, }, +#define AUTOGAIN_IDX 3 { { .id = V4L2_CID_AUTOGAIN, @@ -936,6 +937,14 @@ static int sd_config(struct gspca_dev *gspca_dev, sd->autogain = AUTOGAIN_DEF; sd->ag_cnt = -1; + switch (sd->sensor) { + case SENSOR_OV7630: + case SENSOR_OV7648: + case SENSOR_OV7660: + gspca_dev->ctrl_dis = (1 << AUTOGAIN_IDX); + break; + } + return 0; } @@ -1150,16 +1159,12 @@ static void setautogain(struct gspca_dev *gspca_dev) { struct sd *sd = (struct sd *) gspca_dev; - switch (sd->sensor) { - case SENSOR_HV7131R: - case SENSOR_MO4000: - case SENSOR_MI0360: - if (sd->autogain) - sd->ag_cnt = AG_CNT_START; - else - sd->ag_cnt = -1; - break; - } + if (gspca_dev->ctrl_dis & (1 << AUTOGAIN_IDX)) + return; + if (sd->autogain) + sd->ag_cnt = AG_CNT_START; + else + sd->ag_cnt = -1; } /* -- start the camera -- */ diff --git a/drivers/media/video/gspca/vc032x.c b/drivers/media/video/gspca/vc032x.c index 47c7ce6..5454f0e 100644 --- a/drivers/media/video/gspca/vc032x.c +++ b/drivers/media/video/gspca/vc032x.c @@ -69,6 +69,7 @@ static struct ctrl sd_ctrls[] = { .set = sd_setautogain, .get = sd_getautogain, }, +#define LIGHTFREQ_IDX 1 { { .id = V4L2_CID_POWER_LINE_FREQUENCY, @@ -1463,6 +1464,8 @@ static int sd_config(struct gspca_dev *gspca_dev, sd->qindex = 7; sd->autogain = AUTOGAIN_DEF; sd->lightfreq = FREQ_DEF; + if (sd->sensor != SENSOR_OV7670) + gspca_dev->ctrl_dis = (1 << LIGHTFREQ_IDX); if (sd->bridge == BRIDGE_VC0321) { reg_r(gspca_dev, 0x8a, 0, 3); diff --git a/drivers/media/video/gspca/zc3xx.c b/drivers/media/video/gspca/zc3xx.c index 79436f2..e78b9b7 100644 --- a/drivers/media/video/gspca/zc3xx.c +++ b/drivers/media/video/gspca/zc3xx.c @@ -85,6 +85,7 @@ static int sd_setsharpness(struct gspca_dev *gspca_dev, __s32 val); static int sd_getsharpness(struct gspca_dev *gspca_dev, __s32 *val); static struct ctrl sd_ctrls[] = { +#define BRIGHTNESS_IDX 0 #define SD_BRIGHTNESS 0 { { @@ -141,6 +142,7 @@ static struct ctrl sd_ctrls[] = { .set = sd_setautogain, .get = sd_getautogain, }, +#define LIGHTFREQ_IDX 4 #define SD_FREQ 4 { { @@ -7150,6 +7152,20 @@ static int sd_config(struct gspca_dev *gspca_dev, sd->lightfreq = sd_ctrls[SD_FREQ].qctrl.default_value; sd->sharpness = sd_ctrls[SD_SHARPNESS].qctrl.default_value; + switch (sd->sensor) { + case SENSOR_GC0305: + case SENSOR_OV7620: + case SENSOR_PO2030: + gspca_dev->ctrl_dis = (1 << BRIGHTNESS_IDX); + break; + case SENSOR_HDCS2020: + case SENSOR_HV7131B: + case SENSOR_HV7131C: + case SENSOR_OV7630C: + gspca_dev->ctrl_dis = (1 << LIGHTFREQ_IDX); + break; + } + /* switch the led off */ reg_w(gspca_dev->dev, 0x01, 0x0000); return 0; -- cgit v0.10.2 From 0f523c2ff6b5ab3b4412cf56dee77ac57be24103 Mon Sep 17 00:00:00 2001 From: Hans de Goede Date: Wed, 3 Sep 2008 17:12:14 -0300 Subject: V4L/DVB (8815): gspca: Fix problems with disabled controls. Signed-off-by: Hans de Goede Signed-off-by: Jean-Francois Moine Signed-off-by: Mauro Carvalho Chehab diff --git a/drivers/media/video/gspca/gspca.c b/drivers/media/video/gspca/gspca.c index 33161e1..e7e73ec 100644 --- a/drivers/media/video/gspca/gspca.c +++ b/drivers/media/video/gspca/gspca.c @@ -869,7 +869,7 @@ static int vidioc_queryctrl(struct file *file, void *priv, id &= V4L2_CTRL_ID_MASK; id++; for (i = 0; i < gspca_dev->sd_desc->nctrls; i++) { - if (id < gspca_dev->sd_desc->ctrls[i].qctrl.id) + if (gspca_dev->sd_desc->ctrls[i].qctrl.id < id) continue; if (ix < 0) { ix = i; @@ -908,6 +908,8 @@ static int vidioc_s_ctrl(struct file *file, void *priv, i++, ctrls++) { if (ctrl->id != ctrls->qctrl.id) continue; + if (gspca_dev->ctrl_dis & (1 << i)) + return -EINVAL; if (ctrl->value < ctrls->qctrl.minimum || ctrl->value > ctrls->qctrl.maximum) return -ERANGE; @@ -934,6 +936,8 @@ static int vidioc_g_ctrl(struct file *file, void *priv, i++, ctrls++) { if (ctrl->id != ctrls->qctrl.id) continue; + if (gspca_dev->ctrl_dis & (1 << i)) + return -EINVAL; if (mutex_lock_interruptible(&gspca_dev->usb_lock)) return -ERESTARTSYS; ret = ctrls->get(gspca_dev, &ctrl->value); -- cgit v0.10.2 From e2ad2a54ad1e0f8d7c9e49c38b552a630e015af3 Mon Sep 17 00:00:00 2001 From: Hans de Goede Date: Wed, 3 Sep 2008 17:12:15 -0300 Subject: V4L/DVB (8816): gspca: Set disabled ctrls and fix a register pb with ovxxxx in sonixb. - set some controls as disabled instead of copying the device descr. - in the ov6650 / 7650 exposure code clamp reg 11 before (instead of after) using it to calculate reg 10. - disable brightness (instead of ignoring it) for the TAS5110. Signed-off-by: Hans de Goede Signed-off-by: Jean-Francois Moine Signed-off-by: Mauro Carvalho Chehab diff --git a/drivers/media/video/gspca/sonixb.c b/drivers/media/video/gspca/sonixb.c index e535ced..735d426 100644 --- a/drivers/media/video/gspca/sonixb.c +++ b/drivers/media/video/gspca/sonixb.c @@ -31,9 +31,6 @@ MODULE_LICENSE("GPL"); /* specific webcam descriptor */ struct sd { struct gspca_dev gspca_dev; /* !! must be the first item */ - - struct sd_desc sd_desc; /* our nctrls differ dependend upon the - sensor, so we use a per cam copy */ atomic_t avg_lum; unsigned char gain; @@ -60,9 +57,8 @@ struct sd { /* flags used in the device id table */ #define F_GAIN 0x01 /* has gain */ -#define F_AUTO 0x02 /* has autogain */ -#define F_SIF 0x04 /* sif or vga */ -#define F_H18 0x08 /* long (18 b) or short (12 b) frame header */ +#define F_SIF 0x02 /* sif or vga */ +#define F_H18 0x04 /* long (18 b) or short (12 b) frame header */ #define COMP2 0x8f #define COMP 0xc7 /* 0x87 //0x07 */ @@ -95,6 +91,7 @@ static int sd_setfreq(struct gspca_dev *gspca_dev, __s32 val); static int sd_getfreq(struct gspca_dev *gspca_dev, __s32 *val); static struct ctrl sd_ctrls[] = { +#define BRIGHTNESS_IDX 0 { { .id = V4L2_CID_BRIGHTNESS, @@ -109,6 +106,7 @@ static struct ctrl sd_ctrls[] = { .set = sd_setbrightness, .get = sd_getbrightness, }, +#define GAIN_IDX 1 { { .id = V4L2_CID_GAIN, @@ -124,6 +122,7 @@ static struct ctrl sd_ctrls[] = { .set = sd_setgain, .get = sd_getgain, }, +#define EXPOSURE_IDX 2 { { .id = V4L2_CID_EXPOSURE, @@ -140,6 +139,7 @@ static struct ctrl sd_ctrls[] = { .set = sd_setexposure, .get = sd_getexposure, }, +#define AUTOGAIN_IDX 3 { { .id = V4L2_CID_AUTOGAIN, @@ -155,6 +155,7 @@ static struct ctrl sd_ctrls[] = { .set = sd_setautogain, .get = sd_getautogain, }, +#define FREQ_IDX 4 { { .id = V4L2_CID_POWER_LINE_FREQUENCY, @@ -545,9 +546,6 @@ static void setbrightness(struct gspca_dev *gspca_dev) goto err; break; } - case SENSOR_TAS5110: - /* FIXME figure out howto control brightness on TAS5110 */ - break; } return; err: @@ -665,6 +663,11 @@ static void setexposure(struct gspca_dev *gspca_dev) else if (reg11 > 16) reg11 = 16; + /* In 640x480, if the reg11 has less than 3, the image is + unstable (not enough bandwidth). */ + if (gspca_dev->width == 640 && reg11 < 3) + reg11 = 3; + /* frame exposure time in ms = 1000 * reg11 / 30 -> reg10 = sd->exposure * 2 * reg10_max / (1000 * reg11 / 30) */ reg10 = (sd->exposure * 60 * reg10_max) / (1000 * reg11); @@ -678,11 +681,6 @@ static void setexposure(struct gspca_dev *gspca_dev) else if (reg10 > reg10_max) reg10 = reg10_max; - /* In 640x480, if the reg11 has less than 3, the image is - unstable (not enough bandwidth). */ - if (gspca_dev->width == 640 && reg11 < 3) - reg11 = 3; - /* Write reg 10 and reg11 low nibble */ i2c[1] = sd->sensor_addr; i2c[3] = reg10; @@ -759,23 +757,17 @@ static int sd_config(struct gspca_dev *gspca_dev, struct cam *cam; int sif = 0; - /* nctrls depends upon the sensor, so we use a per cam copy */ - memcpy(&sd->sd_desc, gspca_dev->sd_desc, sizeof(struct sd_desc)); - gspca_dev->sd_desc = &sd->sd_desc; - /* copy the webcam info from the device id */ sd->sensor = (id->driver_info >> 24) & 0xff; if (id->driver_info & (F_GAIN << 16)) sd->sensor_has_gain = 1; - if (id->driver_info & (F_AUTO << 16)) - sd->sd_desc.dq_callback = do_autogain; if (id->driver_info & (F_SIF << 16)) sif = 1; if (id->driver_info & (F_H18 << 16)) sd->fr_h_sz = 18; /* size of frame header */ else sd->fr_h_sz = 12; - sd->sd_desc.nctrls = (id->driver_info >> 8) & 0xff; + gspca_dev->ctrl_dis = (id->driver_info >> 8) & 0xff; sd->sensor_addr = id->driver_info & 0xff; cam = &gspca_dev->cam; @@ -790,7 +782,10 @@ static int sd_config(struct gspca_dev *gspca_dev, sd->brightness = BRIGHTNESS_DEF; sd->gain = GAIN_DEF; sd->exposure = EXPOSURE_DEF; - sd->autogain = AUTOGAIN_DEF; + if (gspca_dev->ctrl_dis & (1 << AUTOGAIN_IDX)) + sd->autogain = 0; /* Disable do_autogain callback */ + else + sd->autogain = AUTOGAIN_DEF; sd->freq = FREQ_DEF; return 0; @@ -1169,50 +1164,55 @@ static const struct sd_desc sd_desc = { .close = sd_close, .pkt_scan = sd_pkt_scan, .querymenu = sd_querymenu, + .dq_callback = do_autogain, }; /* -- module initialisation -- */ -#define SFCI(sensor, flags, nctrls, i2c_addr) \ +#define SFCI(sensor, flags, disable_ctrls, i2c_addr) \ .driver_info = (SENSOR_ ## sensor << 24) \ | ((flags) << 16) \ - | ((nctrls) << 8) \ + | ((disable_ctrls) << 8) \ | (i2c_addr) +#define NO_EXPO ((1 << EXPOSURE_IDX) | (1 << AUTOGAIN_IDX)) +#define NO_FREQ (1 << FREQ_IDX) +#define NO_BRIGHTNESS (1 << BRIGHTNESS_IDX) + static __devinitdata struct usb_device_id device_table[] = { #ifndef CONFIG_USB_SN9C102 {USB_DEVICE(0x0c45, 0x6001), /* SN9C102 */ - SFCI(TAS5110, F_GAIN|F_AUTO|F_SIF, 4, 0)}, + SFCI(TAS5110, F_GAIN|F_SIF, NO_BRIGHTNESS|NO_FREQ, 0)}, {USB_DEVICE(0x0c45, 0x6005), /* SN9C101 */ - SFCI(TAS5110, F_GAIN|F_AUTO|F_SIF, 4, 0)}, + SFCI(TAS5110, F_GAIN|F_SIF, NO_BRIGHTNESS|NO_FREQ, 0)}, {USB_DEVICE(0x0c45, 0x6007), /* SN9C101 */ - SFCI(TAS5110, F_GAIN|F_AUTO|F_SIF, 4, 0)}, + SFCI(TAS5110, F_GAIN|F_SIF, NO_BRIGHTNESS|NO_FREQ, 0)}, {USB_DEVICE(0x0c45, 0x6009), /* SN9C101 */ - SFCI(PAS106, F_SIF, 2, 0)}, + SFCI(PAS106, F_SIF, NO_EXPO|NO_FREQ, 0)}, {USB_DEVICE(0x0c45, 0x600d), /* SN9C101 */ - SFCI(PAS106, F_SIF, 2, 0)}, + SFCI(PAS106, F_SIF, NO_EXPO|NO_FREQ, 0)}, #endif {USB_DEVICE(0x0c45, 0x6011), /* SN9C101 - SN9C101G */ - SFCI(OV6650, F_GAIN|F_AUTO|F_SIF, 5, 0x60)}, + SFCI(OV6650, F_GAIN|F_SIF, 0, 0x60)}, #ifndef CONFIG_USB_SN9C102 {USB_DEVICE(0x0c45, 0x6019), /* SN9C101 */ - SFCI(OV7630, F_GAIN|F_AUTO, 5, 0x21)}, + SFCI(OV7630, F_GAIN, 0, 0x21)}, {USB_DEVICE(0x0c45, 0x6024), /* SN9C102 */ - SFCI(TAS5130CXX, 0, 2, 0)}, + SFCI(TAS5130CXX, 0, NO_EXPO|NO_FREQ, 0)}, {USB_DEVICE(0x0c45, 0x6025), /* SN9C102 */ - SFCI(TAS5130CXX, 0, 2, 0)}, + SFCI(TAS5130CXX, 0, NO_EXPO|NO_FREQ, 0)}, {USB_DEVICE(0x0c45, 0x6028), /* SN9C102 */ - SFCI(PAS202, 0, 2, 0)}, + SFCI(PAS202, 0, NO_EXPO|NO_FREQ, 0)}, {USB_DEVICE(0x0c45, 0x6029), /* SN9C101 */ - SFCI(PAS106, F_SIF, 2, 0)}, + SFCI(PAS106, F_SIF, NO_EXPO|NO_FREQ, 0)}, {USB_DEVICE(0x0c45, 0x602c), /* SN9C102 */ - SFCI(OV7630, F_GAIN|F_AUTO, 5, 0x21)}, + SFCI(OV7630, F_GAIN, 0, 0x21)}, {USB_DEVICE(0x0c45, 0x602d), /* SN9C102 */ - SFCI(HV7131R, 0, 2, 0)}, + SFCI(HV7131R, 0, NO_EXPO|NO_FREQ, 0)}, {USB_DEVICE(0x0c45, 0x602e), /* SN9C102 */ - SFCI(OV7630, F_GAIN|F_AUTO, 5, 0x21)}, + SFCI(OV7630, F_GAIN, 0, 0x21)}, {USB_DEVICE(0x0c45, 0x60af), /* SN9C103 */ - SFCI(PAS202, F_H18, 2, 0)}, + SFCI(PAS202, F_H18, NO_EXPO|NO_FREQ, 0)}, {USB_DEVICE(0x0c45, 0x60b0), /* SN9C103 */ - SFCI(OV7630, F_GAIN|F_AUTO|F_H18, 5, 0x21)}, + SFCI(OV7630, F_GAIN|F_H18, 0, 0x21)}, #endif {} }; -- cgit v0.10.2 From 65f33396ab57f3346fb07ddee8e3aa616d13386c Mon Sep 17 00:00:00 2001 From: Hans de Goede Date: Wed, 3 Sep 2008 17:12:15 -0300 Subject: V4L/DVB (8817): gspca: LED and proble changes in sonixb. - turn the led of the cam off after plugging in the cam - move the probe code from open to config, so that if the probe fails we never register Signed-off-by: Hans de Goede Signed-off-by: Jean-Francois Moine Signed-off-by: Mauro Carvalho Chehab diff --git a/drivers/media/video/gspca/sonixb.c b/drivers/media/video/gspca/sonixb.c index 735d426..64aae06 100644 --- a/drivers/media/video/gspca/sonixb.c +++ b/drivers/media/video/gspca/sonixb.c @@ -756,6 +756,11 @@ static int sd_config(struct gspca_dev *gspca_dev, struct sd *sd = (struct sd *) gspca_dev; struct cam *cam; int sif = 0; + const __u8 stop = 0x09; /* Disable stream turn of LED */ + + reg_r(gspca_dev, 0x00); + if (gspca_dev->usb_buf[0] != 0x10) + return -ENODEV; /* copy the webcam info from the device id */ sd->sensor = (id->driver_info >> 24) & 0xff; @@ -788,15 +793,15 @@ static int sd_config(struct gspca_dev *gspca_dev, sd->autogain = AUTOGAIN_DEF; sd->freq = FREQ_DEF; + /* Disable stream turn of LED */ + reg_w(gspca_dev, 0x01, &stop, 1); + return 0; } /* this function is called at open time */ static int sd_open(struct gspca_dev *gspca_dev) { - reg_r(gspca_dev, 0x00); - if (gspca_dev->usb_buf[0] != 0x10) - return -ENODEV; return 0; } -- cgit v0.10.2 From 1e89e2da48070da8ac221c37fea8fa82da127c34 Mon Sep 17 00:00:00 2001 From: Jean-Francois Moine Date: Wed, 3 Sep 2008 17:12:15 -0300 Subject: V4L/DVB (8818): gspca: Reinitialize the device on resume. Signed-off-by: Jean-Francois Moine Signed-off-by: Mauro Carvalho Chehab diff --git a/drivers/media/video/gspca/gspca.c b/drivers/media/video/gspca/gspca.c index e7e73ec..1767991 100644 --- a/drivers/media/video/gspca/gspca.c +++ b/drivers/media/video/gspca/gspca.c @@ -1838,9 +1838,12 @@ int gspca_resume(struct usb_interface *intf) struct gspca_dev *gspca_dev = usb_get_intfdata(intf); gspca_dev->frozen = 0; - if (!gspca_dev->streaming) - return 0; - return gspca_init_transfer(gspca_dev); + if (gspca_dev->users != 0) { + gspca_dev->sd_desc->open(gspca_dev); + if (gspca_dev->streaming) + return gspca_init_transfer(gspca_dev); + } + return 0; } EXPORT_SYMBOL(gspca_resume); #endif -- cgit v0.10.2 From 4202f71ca1e52d73cab14f3695fdef6b6f010a0b Mon Sep 17 00:00:00 2001 From: Jean-Francois Moine Date: Wed, 3 Sep 2008 17:12:15 -0300 Subject: V4L/DVB (8819): gspca: Initialize the ov519 at open time and source cleanup. Signed-off-by: Jean-Francois Moine Signed-off-by: Mauro Carvalho Chehab diff --git a/drivers/media/video/gspca/ov519.c b/drivers/media/video/gspca/ov519.c index c132f8d..4062aed 100644 --- a/drivers/media/video/gspca/ov519.c +++ b/drivers/media/video/gspca/ov519.c @@ -63,11 +63,10 @@ struct sd { #define SEN_OV6630 2 #define SEN_OV7610 3 #define SEN_OV7620 4 -#define SEN_OV7630 5 -#define SEN_OV7640 6 -#define SEN_OV7670 7 -#define SEN_OV76BE 8 -#define SEN_OV8610 9 +#define SEN_OV7640 5 +#define SEN_OV7670 6 +#define SEN_OV76BE 7 +#define SEN_OV8610 8 }; @@ -293,6 +292,541 @@ static struct v4l2_pix_format sif_mode[] = { #define OV7670_REG_HAECC7 0xaa /* Hist AEC/AGC control 7 */ #define OV7670_REG_BD60MAX 0xab /* 60hz banding step limit */ +struct ov_regvals { + __u8 reg; + __u8 val; +}; +struct ov_i2c_regvals { + __u8 reg; + __u8 val; +}; + +static const struct ov_i2c_regvals norm_6x20[] = { + { 0x12, 0x80 }, /* reset */ + { 0x11, 0x01 }, + { 0x03, 0x60 }, + { 0x05, 0x7f }, /* For when autoadjust is off */ + { 0x07, 0xa8 }, + /* The ratio of 0x0c and 0x0d controls the white point */ + { 0x0c, 0x24 }, + { 0x0d, 0x24 }, + { 0x0f, 0x15 }, /* COMS */ + { 0x10, 0x75 }, /* AEC Exposure time */ + { 0x12, 0x24 }, /* Enable AGC */ + { 0x14, 0x04 }, + /* 0x16: 0x06 helps frame stability with moving objects */ + { 0x16, 0x06 }, +/* { 0x20, 0x30 }, * Aperture correction enable */ + { 0x26, 0xb2 }, /* BLC enable */ + /* 0x28: 0x05 Selects RGB format if RGB on */ + { 0x28, 0x05 }, + { 0x2a, 0x04 }, /* Disable framerate adjust */ +/* { 0x2b, 0xac }, * Framerate; Set 2a[7] first */ + { 0x2d, 0x99 }, + { 0x33, 0xa0 }, /* Color Processing Parameter */ + { 0x34, 0xd2 }, /* Max A/D range */ + { 0x38, 0x8b }, + { 0x39, 0x40 }, + + { 0x3c, 0x39 }, /* Enable AEC mode changing */ + { 0x3c, 0x3c }, /* Change AEC mode */ + { 0x3c, 0x24 }, /* Disable AEC mode changing */ + + { 0x3d, 0x80 }, + /* These next two registers (0x4a, 0x4b) are undocumented. + * They control the color balance */ + { 0x4a, 0x80 }, + { 0x4b, 0x80 }, + { 0x4d, 0xd2 }, /* This reduces noise a bit */ + { 0x4e, 0xc1 }, + { 0x4f, 0x04 }, +/* Do 50-53 have any effect? */ +/* Toggle 0x12[2] off and on here? */ +}; + +static const struct ov_i2c_regvals norm_6x30[] = { + { 0x12, 0x80 }, /* Reset */ + { 0x00, 0x1f }, /* Gain */ + { 0x01, 0x99 }, /* Blue gain */ + { 0x02, 0x7c }, /* Red gain */ + { 0x03, 0xc0 }, /* Saturation */ + { 0x05, 0x0a }, /* Contrast */ + { 0x06, 0x95 }, /* Brightness */ + { 0x07, 0x2d }, /* Sharpness */ + { 0x0c, 0x20 }, + { 0x0d, 0x20 }, + { 0x0e, 0x20 }, + { 0x0f, 0x05 }, + { 0x10, 0x9a }, + { 0x11, 0x00 }, /* Pixel clock = fastest */ + { 0x12, 0x24 }, /* Enable AGC and AWB */ + { 0x13, 0x21 }, + { 0x14, 0x80 }, + { 0x15, 0x01 }, + { 0x16, 0x03 }, + { 0x17, 0x38 }, + { 0x18, 0xea }, + { 0x19, 0x04 }, + { 0x1a, 0x93 }, + { 0x1b, 0x00 }, + { 0x1e, 0xc4 }, + { 0x1f, 0x04 }, + { 0x20, 0x20 }, + { 0x21, 0x10 }, + { 0x22, 0x88 }, + { 0x23, 0xc0 }, /* Crystal circuit power level */ + { 0x25, 0x9a }, /* Increase AEC black ratio */ + { 0x26, 0xb2 }, /* BLC enable */ + { 0x27, 0xa2 }, + { 0x28, 0x00 }, + { 0x29, 0x00 }, + { 0x2a, 0x84 }, /* 60 Hz power */ + { 0x2b, 0xa8 }, /* 60 Hz power */ + { 0x2c, 0xa0 }, + { 0x2d, 0x95 }, /* Enable auto-brightness */ + { 0x2e, 0x88 }, + { 0x33, 0x26 }, + { 0x34, 0x03 }, + { 0x36, 0x8f }, + { 0x37, 0x80 }, + { 0x38, 0x83 }, + { 0x39, 0x80 }, + { 0x3a, 0x0f }, + { 0x3b, 0x3c }, + { 0x3c, 0x1a }, + { 0x3d, 0x80 }, + { 0x3e, 0x80 }, + { 0x3f, 0x0e }, + { 0x40, 0x00 }, /* White bal */ + { 0x41, 0x00 }, /* White bal */ + { 0x42, 0x80 }, + { 0x43, 0x3f }, /* White bal */ + { 0x44, 0x80 }, + { 0x45, 0x20 }, + { 0x46, 0x20 }, + { 0x47, 0x80 }, + { 0x48, 0x7f }, + { 0x49, 0x00 }, + { 0x4a, 0x00 }, + { 0x4b, 0x80 }, + { 0x4c, 0xd0 }, + { 0x4d, 0x10 }, /* U = 0.563u, V = 0.714v */ + { 0x4e, 0x40 }, + { 0x4f, 0x07 }, /* UV avg., col. killer: max */ + { 0x50, 0xff }, + { 0x54, 0x23 }, /* Max AGC gain: 18dB */ + { 0x55, 0xff }, + { 0x56, 0x12 }, + { 0x57, 0x81 }, + { 0x58, 0x75 }, + { 0x59, 0x01 }, /* AGC dark current comp.: +1 */ + { 0x5a, 0x2c }, + { 0x5b, 0x0f }, /* AWB chrominance levels */ + { 0x5c, 0x10 }, + { 0x3d, 0x80 }, + { 0x27, 0xa6 }, + { 0x12, 0x20 }, /* Toggle AWB */ + { 0x12, 0x24 }, +}; + +/* Lawrence Glaister reports: + * + * Register 0x0f in the 7610 has the following effects: + * + * 0x85 (AEC method 1): Best overall, good contrast range + * 0x45 (AEC method 2): Very overexposed + * 0xa5 (spec sheet default): Ok, but the black level is + * shifted resulting in loss of contrast + * 0x05 (old driver setting): very overexposed, too much + * contrast + */ +static const struct ov_i2c_regvals norm_7610[] = { + { 0x10, 0xff }, + { 0x16, 0x06 }, + { 0x28, 0x24 }, + { 0x2b, 0xac }, + { 0x12, 0x00 }, + { 0x38, 0x81 }, + { 0x28, 0x24 }, /* 0c */ + { 0x0f, 0x85 }, /* lg's setting */ + { 0x15, 0x01 }, + { 0x20, 0x1c }, + { 0x23, 0x2a }, + { 0x24, 0x10 }, + { 0x25, 0x8a }, + { 0x26, 0xa2 }, + { 0x27, 0xc2 }, + { 0x2a, 0x04 }, + { 0x2c, 0xfe }, + { 0x2d, 0x93 }, + { 0x30, 0x71 }, + { 0x31, 0x60 }, + { 0x32, 0x26 }, + { 0x33, 0x20 }, + { 0x34, 0x48 }, + { 0x12, 0x24 }, + { 0x11, 0x01 }, + { 0x0c, 0x24 }, + { 0x0d, 0x24 }, +}; + +static const struct ov_i2c_regvals norm_7620[] = { + { 0x00, 0x00 }, /* gain */ + { 0x01, 0x80 }, /* blue gain */ + { 0x02, 0x80 }, /* red gain */ + { 0x03, 0xc0 }, /* OV7670_REG_VREF */ + { 0x06, 0x60 }, + { 0x07, 0x00 }, + { 0x0c, 0x24 }, + { 0x0c, 0x24 }, + { 0x0d, 0x24 }, + { 0x11, 0x01 }, + { 0x12, 0x24 }, + { 0x13, 0x01 }, + { 0x14, 0x84 }, + { 0x15, 0x01 }, + { 0x16, 0x03 }, + { 0x17, 0x2f }, + { 0x18, 0xcf }, + { 0x19, 0x06 }, + { 0x1a, 0xf5 }, + { 0x1b, 0x00 }, + { 0x20, 0x18 }, + { 0x21, 0x80 }, + { 0x22, 0x80 }, + { 0x23, 0x00 }, + { 0x26, 0xa2 }, + { 0x27, 0xea }, + { 0x28, 0x20 }, + { 0x29, 0x00 }, + { 0x2a, 0x10 }, + { 0x2b, 0x00 }, + { 0x2c, 0x88 }, + { 0x2d, 0x91 }, + { 0x2e, 0x80 }, + { 0x2f, 0x44 }, + { 0x60, 0x27 }, + { 0x61, 0x02 }, + { 0x62, 0x5f }, + { 0x63, 0xd5 }, + { 0x64, 0x57 }, + { 0x65, 0x83 }, + { 0x66, 0x55 }, + { 0x67, 0x92 }, + { 0x68, 0xcf }, + { 0x69, 0x76 }, + { 0x6a, 0x22 }, + { 0x6b, 0x00 }, + { 0x6c, 0x02 }, + { 0x6d, 0x44 }, + { 0x6e, 0x80 }, + { 0x6f, 0x1d }, + { 0x70, 0x8b }, + { 0x71, 0x00 }, + { 0x72, 0x14 }, + { 0x73, 0x54 }, + { 0x74, 0x00 }, + { 0x75, 0x8e }, + { 0x76, 0x00 }, + { 0x77, 0xff }, + { 0x78, 0x80 }, + { 0x79, 0x80 }, + { 0x7a, 0x80 }, + { 0x7b, 0xe2 }, + { 0x7c, 0x00 }, +}; + +/* 7640 and 7648. The defaults should be OK for most registers. */ +static const struct ov_i2c_regvals norm_7640[] = { + { 0x12, 0x80 }, + { 0x12, 0x14 }, +}; + +/* 7670. Defaults taken from OmniVision provided data, +* as provided by Jonathan Corbet of OLPC */ +static const struct ov_i2c_regvals norm_7670[] = { + { OV7670_REG_COM7, OV7670_COM7_RESET }, + { OV7670_REG_TSLB, 0x04 }, /* OV */ + { OV7670_REG_COM7, OV7670_COM7_FMT_VGA }, /* VGA */ + { OV7670_REG_CLKRC, 0x01 }, +/* + * Set the hardware window. These values from OV don't entirely + * make sense - hstop is less than hstart. But they work... + */ + { OV7670_REG_HSTART, 0x13 }, + { OV7670_REG_HSTOP, 0x01 }, + { OV7670_REG_HREF, 0xb6 }, + { OV7670_REG_VSTART, 0x02 }, + { OV7670_REG_VSTOP, 0x7a }, + { OV7670_REG_VREF, 0x0a }, + + { OV7670_REG_COM3, 0 }, + { OV7670_REG_COM14, 0 }, +/* Mystery scaling numbers */ + { 0x70, 0x3a }, + { 0x71, 0x35 }, + { 0x72, 0x11 }, + { 0x73, 0xf0 }, + { 0xa2, 0x02 }, +/* { OV7670_REG_COM10, 0x0 }, */ + +/* Gamma curve values */ + { 0x7a, 0x20 }, + { 0x7b, 0x10 }, + { 0x7c, 0x1e }, + { 0x7d, 0x35 }, + { 0x7e, 0x5a }, + { 0x7f, 0x69 }, + { 0x80, 0x76 }, + { 0x81, 0x80 }, + { 0x82, 0x88 }, + { 0x83, 0x8f }, + { 0x84, 0x96 }, + { 0x85, 0xa3 }, + { 0x86, 0xaf }, + { 0x87, 0xc4 }, + { 0x88, 0xd7 }, + { 0x89, 0xe8 }, + +/* AGC and AEC parameters. Note we start by disabling those features, + then turn them only after tweaking the values. */ + { OV7670_REG_COM8, OV7670_COM8_FASTAEC + | OV7670_COM8_AECSTEP + | OV7670_COM8_BFILT }, + { OV7670_REG_GAIN, 0 }, + { OV7670_REG_AECH, 0 }, + { OV7670_REG_COM4, 0x40 }, /* magic reserved bit */ + { OV7670_REG_COM9, 0x18 }, /* 4x gain + magic rsvd bit */ + { OV7670_REG_BD50MAX, 0x05 }, + { OV7670_REG_BD60MAX, 0x07 }, + { OV7670_REG_AEW, 0x95 }, + { OV7670_REG_AEB, 0x33 }, + { OV7670_REG_VPT, 0xe3 }, + { OV7670_REG_HAECC1, 0x78 }, + { OV7670_REG_HAECC2, 0x68 }, + { 0xa1, 0x03 }, /* magic */ + { OV7670_REG_HAECC3, 0xd8 }, + { OV7670_REG_HAECC4, 0xd8 }, + { OV7670_REG_HAECC5, 0xf0 }, + { OV7670_REG_HAECC6, 0x90 }, + { OV7670_REG_HAECC7, 0x94 }, + { OV7670_REG_COM8, OV7670_COM8_FASTAEC + | OV7670_COM8_AECSTEP + | OV7670_COM8_BFILT + | OV7670_COM8_AGC + | OV7670_COM8_AEC }, + +/* Almost all of these are magic "reserved" values. */ + { OV7670_REG_COM5, 0x61 }, + { OV7670_REG_COM6, 0x4b }, + { 0x16, 0x02 }, + { OV7670_REG_MVFP, 0x07 }, + { 0x21, 0x02 }, + { 0x22, 0x91 }, + { 0x29, 0x07 }, + { 0x33, 0x0b }, + { 0x35, 0x0b }, + { 0x37, 0x1d }, + { 0x38, 0x71 }, + { 0x39, 0x2a }, + { OV7670_REG_COM12, 0x78 }, + { 0x4d, 0x40 }, + { 0x4e, 0x20 }, + { OV7670_REG_GFIX, 0 }, + { 0x6b, 0x4a }, + { 0x74, 0x10 }, + { 0x8d, 0x4f }, + { 0x8e, 0 }, + { 0x8f, 0 }, + { 0x90, 0 }, + { 0x91, 0 }, + { 0x96, 0 }, + { 0x9a, 0 }, + { 0xb0, 0x84 }, + { 0xb1, 0x0c }, + { 0xb2, 0x0e }, + { 0xb3, 0x82 }, + { 0xb8, 0x0a }, + +/* More reserved magic, some of which tweaks white balance */ + { 0x43, 0x0a }, + { 0x44, 0xf0 }, + { 0x45, 0x34 }, + { 0x46, 0x58 }, + { 0x47, 0x28 }, + { 0x48, 0x3a }, + { 0x59, 0x88 }, + { 0x5a, 0x88 }, + { 0x5b, 0x44 }, + { 0x5c, 0x67 }, + { 0x5d, 0x49 }, + { 0x5e, 0x0e }, + { 0x6c, 0x0a }, + { 0x6d, 0x55 }, + { 0x6e, 0x11 }, + { 0x6f, 0x9f }, + /* "9e for advance AWB" */ + { 0x6a, 0x40 }, + { OV7670_REG_BLUE, 0x40 }, + { OV7670_REG_RED, 0x60 }, + { OV7670_REG_COM8, OV7670_COM8_FASTAEC + | OV7670_COM8_AECSTEP + | OV7670_COM8_BFILT + | OV7670_COM8_AGC + | OV7670_COM8_AEC + | OV7670_COM8_AWB }, + +/* Matrix coefficients */ + { 0x4f, 0x80 }, + { 0x50, 0x80 }, + { 0x51, 0 }, + { 0x52, 0x22 }, + { 0x53, 0x5e }, + { 0x54, 0x80 }, + { 0x58, 0x9e }, + + { OV7670_REG_COM16, OV7670_COM16_AWBGAIN }, + { OV7670_REG_EDGE, 0 }, + { 0x75, 0x05 }, + { 0x76, 0xe1 }, + { 0x4c, 0 }, + { 0x77, 0x01 }, + { OV7670_REG_COM13, OV7670_COM13_GAMMA + | OV7670_COM13_UVSAT + | 2}, /* was 3 */ + { 0x4b, 0x09 }, + { 0xc9, 0x60 }, + { OV7670_REG_COM16, 0x38 }, + { 0x56, 0x40 }, + + { 0x34, 0x11 }, + { OV7670_REG_COM11, OV7670_COM11_EXP|OV7670_COM11_HZAUTO }, + { 0xa4, 0x88 }, + { 0x96, 0 }, + { 0x97, 0x30 }, + { 0x98, 0x20 }, + { 0x99, 0x30 }, + { 0x9a, 0x84 }, + { 0x9b, 0x29 }, + { 0x9c, 0x03 }, + { 0x9d, 0x4c }, + { 0x9e, 0x3f }, + { 0x78, 0x04 }, + +/* Extra-weird stuff. Some sort of multiplexor register */ + { 0x79, 0x01 }, + { 0xc8, 0xf0 }, + { 0x79, 0x0f }, + { 0xc8, 0x00 }, + { 0x79, 0x10 }, + { 0xc8, 0x7e }, + { 0x79, 0x0a }, + { 0xc8, 0x80 }, + { 0x79, 0x0b }, + { 0xc8, 0x01 }, + { 0x79, 0x0c }, + { 0xc8, 0x0f }, + { 0x79, 0x0d }, + { 0xc8, 0x20 }, + { 0x79, 0x09 }, + { 0xc8, 0x80 }, + { 0x79, 0x02 }, + { 0xc8, 0xc0 }, + { 0x79, 0x03 }, + { 0xc8, 0x40 }, + { 0x79, 0x05 }, + { 0xc8, 0x30 }, + { 0x79, 0x26 }, +}; + +static const struct ov_i2c_regvals norm_8610[] = { + { 0x12, 0x80 }, + { 0x00, 0x00 }, + { 0x01, 0x80 }, + { 0x02, 0x80 }, + { 0x03, 0xc0 }, + { 0x04, 0x30 }, + { 0x05, 0x30 }, /* was 0x10, new from windrv 090403 */ + { 0x06, 0x70 }, /* was 0x80, new from windrv 090403 */ + { 0x0a, 0x86 }, + { 0x0b, 0xb0 }, + { 0x0c, 0x20 }, + { 0x0d, 0x20 }, + { 0x11, 0x01 }, + { 0x12, 0x25 }, + { 0x13, 0x01 }, + { 0x14, 0x04 }, + { 0x15, 0x01 }, /* Lin and Win think different about UV order */ + { 0x16, 0x03 }, + { 0x17, 0x38 }, /* was 0x2f, new from windrv 090403 */ + { 0x18, 0xea }, /* was 0xcf, new from windrv 090403 */ + { 0x19, 0x02 }, /* was 0x06, new from windrv 090403 */ + { 0x1a, 0xf5 }, + { 0x1b, 0x00 }, + { 0x20, 0xd0 }, /* was 0x90, new from windrv 090403 */ + { 0x23, 0xc0 }, /* was 0x00, new from windrv 090403 */ + { 0x24, 0x30 }, /* was 0x1d, new from windrv 090403 */ + { 0x25, 0x50 }, /* was 0x57, new from windrv 090403 */ + { 0x26, 0xa2 }, + { 0x27, 0xea }, + { 0x28, 0x00 }, + { 0x29, 0x00 }, + { 0x2a, 0x80 }, + { 0x2b, 0xc8 }, /* was 0xcc, new from windrv 090403 */ + { 0x2c, 0xac }, + { 0x2d, 0x45 }, /* was 0xd5, new from windrv 090403 */ + { 0x2e, 0x80 }, + { 0x2f, 0x14 }, /* was 0x01, new from windrv 090403 */ + { 0x4c, 0x00 }, + { 0x4d, 0x30 }, /* was 0x10, new from windrv 090403 */ + { 0x60, 0x02 }, /* was 0x01, new from windrv 090403 */ + { 0x61, 0x00 }, /* was 0x09, new from windrv 090403 */ + { 0x62, 0x5f }, /* was 0xd7, new from windrv 090403 */ + { 0x63, 0xff }, + { 0x64, 0x53 }, /* new windrv 090403 says 0x57, + * maybe thats wrong */ + { 0x65, 0x00 }, + { 0x66, 0x55 }, + { 0x67, 0xb0 }, + { 0x68, 0xc0 }, /* was 0xaf, new from windrv 090403 */ + { 0x69, 0x02 }, + { 0x6a, 0x22 }, + { 0x6b, 0x00 }, + { 0x6c, 0x99 }, /* was 0x80, old windrv says 0x00, but + * deleting bit7 colors the first images red */ + { 0x6d, 0x11 }, /* was 0x00, new from windrv 090403 */ + { 0x6e, 0x11 }, /* was 0x00, new from windrv 090403 */ + { 0x6f, 0x01 }, + { 0x70, 0x8b }, + { 0x71, 0x00 }, + { 0x72, 0x14 }, + { 0x73, 0x54 }, + { 0x74, 0x00 },/* 0x60? - was 0x00, new from windrv 090403 */ + { 0x75, 0x0e }, + { 0x76, 0x02 }, /* was 0x02, new from windrv 090403 */ + { 0x77, 0xff }, + { 0x78, 0x80 }, + { 0x79, 0x80 }, + { 0x7a, 0x80 }, + { 0x7b, 0x10 }, /* was 0x13, new from windrv 090403 */ + { 0x7c, 0x00 }, + { 0x7d, 0x08 }, /* was 0x09, new from windrv 090403 */ + { 0x7e, 0x08 }, /* was 0xc0, new from windrv 090403 */ + { 0x7f, 0xfb }, + { 0x80, 0x28 }, + { 0x81, 0x00 }, + { 0x82, 0x23 }, + { 0x83, 0x0b }, + { 0x84, 0x00 }, + { 0x85, 0x62 }, /* was 0x61, new from windrv 090403 */ + { 0x86, 0xc9 }, + { 0x87, 0x00 }, + { 0x88, 0x00 }, + { 0x89, 0x01 }, + { 0x12, 0x20 }, + { 0x12, 0x25 }, /* was 0x24, new from windrv 090403 */ +}; + static unsigned char ov7670_abs_to_sm(unsigned char v) { if (v > 127) @@ -537,18 +1071,10 @@ static int ov51x_set_slave_ids(struct sd *sd, rc = reg_w(sd, R51x_I2C_W_SID, slave); if (rc < 0) return rc; + sd->primary_i2c_slave = slave; return reg_w(sd, R51x_I2C_R_SID, slave + 1); } -struct ov_regvals { - __u8 reg; - __u8 val; -}; -struct ov_i2c_regvals { - __u8 reg; - __u8 val; -}; - static int write_regvals(struct sd *sd, const struct ov_regvals *regvals, int n) @@ -591,101 +1117,9 @@ static int write_i2c_regvals(struct sd *sd, static int ov8xx0_configure(struct sd *sd) { int rc; - static const struct ov_i2c_regvals norm_8610[] = { - { 0x12, 0x80 }, - { 0x00, 0x00 }, - { 0x01, 0x80 }, - { 0x02, 0x80 }, - { 0x03, 0xc0 }, - { 0x04, 0x30 }, - { 0x05, 0x30 }, /* was 0x10, new from windrv 090403 */ - { 0x06, 0x70 }, /* was 0x80, new from windrv 090403 */ - { 0x0a, 0x86 }, - { 0x0b, 0xb0 }, - { 0x0c, 0x20 }, - { 0x0d, 0x20 }, - { 0x11, 0x01 }, - { 0x12, 0x25 }, - { 0x13, 0x01 }, - { 0x14, 0x04 }, - { 0x15, 0x01 }, /* Lin and Win think different about UV order */ - { 0x16, 0x03 }, - { 0x17, 0x38 }, /* was 0x2f, new from windrv 090403 */ - { 0x18, 0xea }, /* was 0xcf, new from windrv 090403 */ - { 0x19, 0x02 }, /* was 0x06, new from windrv 090403 */ - { 0x1a, 0xf5 }, - { 0x1b, 0x00 }, - { 0x20, 0xd0 }, /* was 0x90, new from windrv 090403 */ - { 0x23, 0xc0 }, /* was 0x00, new from windrv 090403 */ - { 0x24, 0x30 }, /* was 0x1d, new from windrv 090403 */ - { 0x25, 0x50 }, /* was 0x57, new from windrv 090403 */ - { 0x26, 0xa2 }, - { 0x27, 0xea }, - { 0x28, 0x00 }, - { 0x29, 0x00 }, - { 0x2a, 0x80 }, - { 0x2b, 0xc8 }, /* was 0xcc, new from windrv 090403 */ - { 0x2c, 0xac }, - { 0x2d, 0x45 }, /* was 0xd5, new from windrv 090403 */ - { 0x2e, 0x80 }, - { 0x2f, 0x14 }, /* was 0x01, new from windrv 090403 */ - { 0x4c, 0x00 }, - { 0x4d, 0x30 }, /* was 0x10, new from windrv 090403 */ - { 0x60, 0x02 }, /* was 0x01, new from windrv 090403 */ - { 0x61, 0x00 }, /* was 0x09, new from windrv 090403 */ - { 0x62, 0x5f }, /* was 0xd7, new from windrv 090403 */ - { 0x63, 0xff }, - { 0x64, 0x53 }, /* new windrv 090403 says 0x57, - * maybe thats wrong */ - { 0x65, 0x00 }, - { 0x66, 0x55 }, - { 0x67, 0xb0 }, - { 0x68, 0xc0 }, /* was 0xaf, new from windrv 090403 */ - { 0x69, 0x02 }, - { 0x6a, 0x22 }, - { 0x6b, 0x00 }, - { 0x6c, 0x99 }, /* was 0x80, old windrv says 0x00, but - deleting bit7 colors the first images red */ - { 0x6d, 0x11 }, /* was 0x00, new from windrv 090403 */ - { 0x6e, 0x11 }, /* was 0x00, new from windrv 090403 */ - { 0x6f, 0x01 }, - { 0x70, 0x8b }, - { 0x71, 0x00 }, - { 0x72, 0x14 }, - { 0x73, 0x54 }, - { 0x74, 0x00 },/* 0x60? - was 0x00, new from windrv 090403 */ - { 0x75, 0x0e }, - { 0x76, 0x02 }, /* was 0x02, new from windrv 090403 */ - { 0x77, 0xff }, - { 0x78, 0x80 }, - { 0x79, 0x80 }, - { 0x7a, 0x80 }, - { 0x7b, 0x10 }, /* was 0x13, new from windrv 090403 */ - { 0x7c, 0x00 }, - { 0x7d, 0x08 }, /* was 0x09, new from windrv 090403 */ - { 0x7e, 0x08 }, /* was 0xc0, new from windrv 090403 */ - { 0x7f, 0xfb }, - { 0x80, 0x28 }, - { 0x81, 0x00 }, - { 0x82, 0x23 }, - { 0x83, 0x0b }, - { 0x84, 0x00 }, - { 0x85, 0x62 }, /* was 0x61, new from windrv 090403 */ - { 0x86, 0xc9 }, - { 0x87, 0x00 }, - { 0x88, 0x00 }, - { 0x89, 0x01 }, - { 0x12, 0x20 }, - { 0x12, 0x25 }, /* was 0x24, new from windrv 090403 */ - }; PDEBUG(D_PROBE, "starting ov8xx0 configuration"); - if (init_ov_sensor(sd) < 0) - PDEBUG(D_ERR|D_PROBE, "Failed to read sensor ID"); - else - PDEBUG(D_PROBE, "OV86x0 initialized"); - /* Detect sensor (sub)type */ rc = i2c_r(sd, OV7610_REG_COM_I); if (rc < 0) { @@ -698,9 +1132,6 @@ static int ov8xx0_configure(struct sd *sd) PDEBUG(D_ERR, "Unknown image sensor version: %d", rc & 3); return -1; } - PDEBUG(D_PROBE, "Writing 8610 registers"); - if (write_i2c_regvals(sd, norm_8610, ARRAY_SIZE(norm_8610))) - return -1; /* Set sensor-specific vars */ /* sd->sif = 0; already done */ @@ -714,252 +1145,6 @@ static int ov7xx0_configure(struct sd *sd) { int rc, high, low; - /* Lawrence Glaister reports: - * - * Register 0x0f in the 7610 has the following effects: - * - * 0x85 (AEC method 1): Best overall, good contrast range - * 0x45 (AEC method 2): Very overexposed - * 0xa5 (spec sheet default): Ok, but the black level is - * shifted resulting in loss of contrast - * 0x05 (old driver setting): very overexposed, too much - * contrast - */ - static const struct ov_i2c_regvals norm_7610[] = { - { 0x10, 0xff }, - { 0x16, 0x06 }, - { 0x28, 0x24 }, - { 0x2b, 0xac }, - { 0x12, 0x00 }, - { 0x38, 0x81 }, - { 0x28, 0x24 }, /* 0c */ - { 0x0f, 0x85 }, /* lg's setting */ - { 0x15, 0x01 }, - { 0x20, 0x1c }, - { 0x23, 0x2a }, - { 0x24, 0x10 }, - { 0x25, 0x8a }, - { 0x26, 0xa2 }, - { 0x27, 0xc2 }, - { 0x2a, 0x04 }, - { 0x2c, 0xfe }, - { 0x2d, 0x93 }, - { 0x30, 0x71 }, - { 0x31, 0x60 }, - { 0x32, 0x26 }, - { 0x33, 0x20 }, - { 0x34, 0x48 }, - { 0x12, 0x24 }, - { 0x11, 0x01 }, - { 0x0c, 0x24 }, - { 0x0d, 0x24 }, - }; - - static const struct ov_i2c_regvals norm_7620[] = { - { 0x00, 0x00 }, /* gain */ - { 0x01, 0x80 }, /* blue gain */ - { 0x02, 0x80 }, /* red gain */ - { 0x03, 0xc0 }, /* OV7670_REG_VREF */ - { 0x06, 0x60 }, - { 0x07, 0x00 }, - { 0x0c, 0x24 }, - { 0x0c, 0x24 }, - { 0x0d, 0x24 }, - { 0x11, 0x01 }, - { 0x12, 0x24 }, - { 0x13, 0x01 }, - { 0x14, 0x84 }, - { 0x15, 0x01 }, - { 0x16, 0x03 }, - { 0x17, 0x2f }, - { 0x18, 0xcf }, - { 0x19, 0x06 }, - { 0x1a, 0xf5 }, - { 0x1b, 0x00 }, - { 0x20, 0x18 }, - { 0x21, 0x80 }, - { 0x22, 0x80 }, - { 0x23, 0x00 }, - { 0x26, 0xa2 }, - { 0x27, 0xea }, - { 0x28, 0x20 }, - { 0x29, 0x00 }, - { 0x2a, 0x10 }, - { 0x2b, 0x00 }, - { 0x2c, 0x88 }, - { 0x2d, 0x91 }, - { 0x2e, 0x80 }, - { 0x2f, 0x44 }, - { 0x60, 0x27 }, - { 0x61, 0x02 }, - { 0x62, 0x5f }, - { 0x63, 0xd5 }, - { 0x64, 0x57 }, - { 0x65, 0x83 }, - { 0x66, 0x55 }, - { 0x67, 0x92 }, - { 0x68, 0xcf }, - { 0x69, 0x76 }, - { 0x6a, 0x22 }, - { 0x6b, 0x00 }, - { 0x6c, 0x02 }, - { 0x6d, 0x44 }, - { 0x6e, 0x80 }, - { 0x6f, 0x1d }, - { 0x70, 0x8b }, - { 0x71, 0x00 }, - { 0x72, 0x14 }, - { 0x73, 0x54 }, - { 0x74, 0x00 }, - { 0x75, 0x8e }, - { 0x76, 0x00 }, - { 0x77, 0xff }, - { 0x78, 0x80 }, - { 0x79, 0x80 }, - { 0x7a, 0x80 }, - { 0x7b, 0xe2 }, - { 0x7c, 0x00 }, - }; - - /* 7640 and 7648. The defaults should be OK for most registers. */ - static const struct ov_i2c_regvals norm_7640[] = { - { 0x12, 0x80 }, - { 0x12, 0x14 }, - }; - - /* 7670. Defaults taken from OmniVision provided data, - * as provided by Jonathan Corbet of OLPC */ - static const struct ov_i2c_regvals norm_7670[] = { - { OV7670_REG_COM7, OV7670_COM7_RESET }, - { OV7670_REG_TSLB, 0x04 }, /* OV */ - { OV7670_REG_COM7, OV7670_COM7_FMT_VGA }, /* VGA */ - { OV7670_REG_CLKRC, 0x01 }, - /* - * Set the hardware window. These values from OV don't entirely - * make sense - hstop is less than hstart. But they work... - */ - { OV7670_REG_HSTART, 0x13 }, { OV7670_REG_HSTOP, 0x01 }, - { OV7670_REG_HREF, 0xb6 }, { OV7670_REG_VSTART, 0x02 }, - { OV7670_REG_VSTOP, 0x7a }, { OV7670_REG_VREF, 0x0a }, - - { OV7670_REG_COM3, 0 }, { OV7670_REG_COM14, 0 }, - /* Mystery scaling numbers */ - { 0x70, 0x3a }, { 0x71, 0x35 }, - { 0x72, 0x11 }, { 0x73, 0xf0 }, - { 0xa2, 0x02 }, -/* { OV7670_REG_COM10, 0x0 }, */ - - /* Gamma curve values */ - { 0x7a, 0x20 }, - { 0x7b, 0x10 }, - { 0x7c, 0x1e }, - { 0x7d, 0x35 }, - { 0x7e, 0x5a }, { 0x7f, 0x69 }, - { 0x80, 0x76 }, { 0x81, 0x80 }, - { 0x82, 0x88 }, { 0x83, 0x8f }, - { 0x84, 0x96 }, { 0x85, 0xa3 }, - { 0x86, 0xaf }, { 0x87, 0xc4 }, - { 0x88, 0xd7 }, { 0x89, 0xe8 }, - - /* AGC and AEC parameters. Note we start by disabling those features, - then turn them only after tweaking the values. */ - { OV7670_REG_COM8, OV7670_COM8_FASTAEC - | OV7670_COM8_AECSTEP - | OV7670_COM8_BFILT }, - { OV7670_REG_GAIN, 0 }, { OV7670_REG_AECH, 0 }, - { OV7670_REG_COM4, 0x40 }, /* magic reserved bit */ - { OV7670_REG_COM9, 0x18 }, /* 4x gain + magic rsvd bit */ - { OV7670_REG_BD50MAX, 0x05 }, { OV7670_REG_BD60MAX, 0x07 }, - { OV7670_REG_AEW, 0x95 }, { OV7670_REG_AEB, 0x33 }, - { OV7670_REG_VPT, 0xe3 }, { OV7670_REG_HAECC1, 0x78 }, - { OV7670_REG_HAECC2, 0x68 }, - { 0xa1, 0x03 }, /* magic */ - { OV7670_REG_HAECC3, 0xd8 }, { OV7670_REG_HAECC4, 0xd8 }, - { OV7670_REG_HAECC5, 0xf0 }, { OV7670_REG_HAECC6, 0x90 }, - { OV7670_REG_HAECC7, 0x94 }, - { OV7670_REG_COM8, OV7670_COM8_FASTAEC - | OV7670_COM8_AECSTEP - | OV7670_COM8_BFILT - | OV7670_COM8_AGC - | OV7670_COM8_AEC }, - - /* Almost all of these are magic "reserved" values. */ - { OV7670_REG_COM5, 0x61 }, { OV7670_REG_COM6, 0x4b }, - { 0x16, 0x02 }, - { OV7670_REG_MVFP, 0x07 }, - { 0x21, 0x02 }, { 0x22, 0x91 }, - { 0x29, 0x07 }, { 0x33, 0x0b }, - { 0x35, 0x0b }, { 0x37, 0x1d }, - { 0x38, 0x71 }, { 0x39, 0x2a }, - { OV7670_REG_COM12, 0x78 }, { 0x4d, 0x40 }, - { 0x4e, 0x20 }, { OV7670_REG_GFIX, 0 }, - { 0x6b, 0x4a }, { 0x74, 0x10 }, - { 0x8d, 0x4f }, { 0x8e, 0 }, - { 0x8f, 0 }, { 0x90, 0 }, - { 0x91, 0 }, { 0x96, 0 }, - { 0x9a, 0 }, { 0xb0, 0x84 }, - { 0xb1, 0x0c }, { 0xb2, 0x0e }, - { 0xb3, 0x82 }, { 0xb8, 0x0a }, - - /* More reserved magic, some of which tweaks white balance */ - { 0x43, 0x0a }, { 0x44, 0xf0 }, - { 0x45, 0x34 }, { 0x46, 0x58 }, - { 0x47, 0x28 }, { 0x48, 0x3a }, - { 0x59, 0x88 }, { 0x5a, 0x88 }, - { 0x5b, 0x44 }, { 0x5c, 0x67 }, - { 0x5d, 0x49 }, { 0x5e, 0x0e }, - { 0x6c, 0x0a }, { 0x6d, 0x55 }, - { 0x6e, 0x11 }, { 0x6f, 0x9f }, - /* "9e for advance AWB" */ - { 0x6a, 0x40 }, { OV7670_REG_BLUE, 0x40 }, - { OV7670_REG_RED, 0x60 }, - { OV7670_REG_COM8, OV7670_COM8_FASTAEC - | OV7670_COM8_AECSTEP - | OV7670_COM8_BFILT - | OV7670_COM8_AGC - | OV7670_COM8_AEC - | OV7670_COM8_AWB }, - - /* Matrix coefficients */ - { 0x4f, 0x80 }, { 0x50, 0x80 }, - { 0x51, 0 }, { 0x52, 0x22 }, - { 0x53, 0x5e }, { 0x54, 0x80 }, - { 0x58, 0x9e }, - - { OV7670_REG_COM16, OV7670_COM16_AWBGAIN }, - { OV7670_REG_EDGE, 0 }, - { 0x75, 0x05 }, { 0x76, 0xe1 }, - { 0x4c, 0 }, { 0x77, 0x01 }, - { OV7670_REG_COM13, OV7670_COM13_GAMMA - | OV7670_COM13_UVSAT - | 2}, /* was 3 */ - { 0x4b, 0x09 }, - { 0xc9, 0x60 }, { OV7670_REG_COM16, 0x38 }, - { 0x56, 0x40 }, - - { 0x34, 0x11 }, - { OV7670_REG_COM11, OV7670_COM11_EXP|OV7670_COM11_HZAUTO }, - { 0xa4, 0x88 }, { 0x96, 0 }, - { 0x97, 0x30 }, { 0x98, 0x20 }, - { 0x99, 0x30 }, { 0x9a, 0x84 }, - { 0x9b, 0x29 }, { 0x9c, 0x03 }, - { 0x9d, 0x4c }, { 0x9e, 0x3f }, - { 0x78, 0x04 }, - - /* Extra-weird stuff. Some sort of multiplexor register */ - { 0x79, 0x01 }, { 0xc8, 0xf0 }, - { 0x79, 0x0f }, { 0xc8, 0x00 }, - { 0x79, 0x10 }, { 0xc8, 0x7e }, - { 0x79, 0x0a }, { 0xc8, 0x80 }, - { 0x79, 0x0b }, { 0xc8, 0x01 }, - { 0x79, 0x0c }, { 0xc8, 0x0f }, - { 0x79, 0x0d }, { 0xc8, 0x20 }, - { 0x79, 0x09 }, { 0xc8, 0x80 }, - { 0x79, 0x02 }, { 0xc8, 0xc0 }, - { 0x79, 0x03 }, { 0xc8, 0x40 }, - { 0x79, 0x05 }, { 0xc8, 0x30 }, - { 0x79, 0x26 }, - }; PDEBUG(D_PROBE, "starting OV7xx0 configuration"); @@ -1011,8 +1196,9 @@ static int ov7xx0_configure(struct sd *sd) switch (low) { case 0x30: PDEBUG(D_PROBE, "Sensor is an OV7630/OV7635"); - sd->sensor = SEN_OV7630; - break; + PDEBUG(D_ERR, + "7630 is not supported by this driver"); + return -1; case 0x40: PDEBUG(D_PROBE, "Sensor is an OV7645"); sd->sensor = SEN_OV7640; /* FIXME */ @@ -1038,32 +1224,6 @@ static int ov7xx0_configure(struct sd *sd) return -1; } - switch (sd->sensor) { - case SEN_OV7620: - PDEBUG(D_PROBE, "Writing 7620 registers"); - if (write_i2c_regvals(sd, norm_7620, ARRAY_SIZE(norm_7620))) - return -1; - break; - case SEN_OV7630: - PDEBUG(D_ERR, "7630 is not supported by this driver version"); - return -1; - case SEN_OV7640: - PDEBUG(D_PROBE, "Writing 7640 registers"); - if (write_i2c_regvals(sd, norm_7640, ARRAY_SIZE(norm_7640))) - return -1; - break; - case SEN_OV7670: - PDEBUG(D_PROBE, "Writing 7670 registers"); - if (write_i2c_regvals(sd, norm_7670, ARRAY_SIZE(norm_7670))) - return -1; - break; - default: - PDEBUG(D_PROBE, "Writing 7610 registers"); - if (write_i2c_regvals(sd, norm_7610, ARRAY_SIZE(norm_7610))) - return -1; - break; - } - /* Set sensor-specific vars */ /* sd->sif = 0; already done */ return 0; @@ -1073,141 +1233,7 @@ static int ov7xx0_configure(struct sd *sd) static int ov6xx0_configure(struct sd *sd) { int rc; - static const struct ov_i2c_regvals norm_6x20[] = { - { 0x12, 0x80 }, /* reset */ - { 0x11, 0x01 }, - { 0x03, 0x60 }, - { 0x05, 0x7f }, /* For when autoadjust is off */ - { 0x07, 0xa8 }, - /* The ratio of 0x0c and 0x0d controls the white point */ - { 0x0c, 0x24 }, - { 0x0d, 0x24 }, - { 0x0f, 0x15 }, /* COMS */ - { 0x10, 0x75 }, /* AEC Exposure time */ - { 0x12, 0x24 }, /* Enable AGC */ - { 0x14, 0x04 }, - /* 0x16: 0x06 helps frame stability with moving objects */ - { 0x16, 0x06 }, -/* { 0x20, 0x30 }, * Aperture correction enable */ - { 0x26, 0xb2 }, /* BLC enable */ - /* 0x28: 0x05 Selects RGB format if RGB on */ - { 0x28, 0x05 }, - { 0x2a, 0x04 }, /* Disable framerate adjust */ -/* { 0x2b, 0xac }, * Framerate; Set 2a[7] first */ - { 0x2d, 0x99 }, - { 0x33, 0xa0 }, /* Color Processing Parameter */ - { 0x34, 0xd2 }, /* Max A/D range */ - { 0x38, 0x8b }, - { 0x39, 0x40 }, - - { 0x3c, 0x39 }, /* Enable AEC mode changing */ - { 0x3c, 0x3c }, /* Change AEC mode */ - { 0x3c, 0x24 }, /* Disable AEC mode changing */ - - { 0x3d, 0x80 }, - /* These next two registers (0x4a, 0x4b) are undocumented. - * They control the color balance */ - { 0x4a, 0x80 }, - { 0x4b, 0x80 }, - { 0x4d, 0xd2 }, /* This reduces noise a bit */ - { 0x4e, 0xc1 }, - { 0x4f, 0x04 }, -/* Do 50-53 have any effect? */ -/* Toggle 0x12[2] off and on here? */ - }; - - static const struct ov_i2c_regvals norm_6x30[] = { - { 0x12, 0x80 }, /* Reset */ - { 0x00, 0x1f }, /* Gain */ - { 0x01, 0x99 }, /* Blue gain */ - { 0x02, 0x7c }, /* Red gain */ - { 0x03, 0xc0 }, /* Saturation */ - { 0x05, 0x0a }, /* Contrast */ - { 0x06, 0x95 }, /* Brightness */ - { 0x07, 0x2d }, /* Sharpness */ - { 0x0c, 0x20 }, - { 0x0d, 0x20 }, - { 0x0e, 0x20 }, - { 0x0f, 0x05 }, - { 0x10, 0x9a }, - { 0x11, 0x00 }, /* Pixel clock = fastest */ - { 0x12, 0x24 }, /* Enable AGC and AWB */ - { 0x13, 0x21 }, - { 0x14, 0x80 }, - { 0x15, 0x01 }, - { 0x16, 0x03 }, - { 0x17, 0x38 }, - { 0x18, 0xea }, - { 0x19, 0x04 }, - { 0x1a, 0x93 }, - { 0x1b, 0x00 }, - { 0x1e, 0xc4 }, - { 0x1f, 0x04 }, - { 0x20, 0x20 }, - { 0x21, 0x10 }, - { 0x22, 0x88 }, - { 0x23, 0xc0 }, /* Crystal circuit power level */ - { 0x25, 0x9a }, /* Increase AEC black ratio */ - { 0x26, 0xb2 }, /* BLC enable */ - { 0x27, 0xa2 }, - { 0x28, 0x00 }, - { 0x29, 0x00 }, - { 0x2a, 0x84 }, /* 60 Hz power */ - { 0x2b, 0xa8 }, /* 60 Hz power */ - { 0x2c, 0xa0 }, - { 0x2d, 0x95 }, /* Enable auto-brightness */ - { 0x2e, 0x88 }, - { 0x33, 0x26 }, - { 0x34, 0x03 }, - { 0x36, 0x8f }, - { 0x37, 0x80 }, - { 0x38, 0x83 }, - { 0x39, 0x80 }, - { 0x3a, 0x0f }, - { 0x3b, 0x3c }, - { 0x3c, 0x1a }, - { 0x3d, 0x80 }, - { 0x3e, 0x80 }, - { 0x3f, 0x0e }, - { 0x40, 0x00 }, /* White bal */ - { 0x41, 0x00 }, /* White bal */ - { 0x42, 0x80 }, - { 0x43, 0x3f }, /* White bal */ - { 0x44, 0x80 }, - { 0x45, 0x20 }, - { 0x46, 0x20 }, - { 0x47, 0x80 }, - { 0x48, 0x7f }, - { 0x49, 0x00 }, - { 0x4a, 0x00 }, - { 0x4b, 0x80 }, - { 0x4c, 0xd0 }, - { 0x4d, 0x10 }, /* U = 0.563u, V = 0.714v */ - { 0x4e, 0x40 }, - { 0x4f, 0x07 }, /* UV avg., col. killer: max */ - { 0x50, 0xff }, - { 0x54, 0x23 }, /* Max AGC gain: 18dB */ - { 0x55, 0xff }, - { 0x56, 0x12 }, - { 0x57, 0x81 }, - { 0x58, 0x75 }, - { 0x59, 0x01 }, /* AGC dark current comp.: +1 */ - { 0x5a, 0x2c }, - { 0x5b, 0x0f }, /* AWB chrominance levels */ - { 0x5c, 0x10 }, - { 0x3d, 0x80 }, - { 0x27, 0xa6 }, - { 0x12, 0x20 }, /* Toggle AWB */ - { 0x12, 0x24 }, - }; - - PDEBUG(D_PROBE, "starting sensor configuration"); - - if (init_ov_sensor(sd) < 0) { - PDEBUG(D_ERR, "Failed to read sensor ID."); - return -1; - } - PDEBUG(D_PROBE, "OV6xx0 sensor detected"); + PDEBUG(D_PROBE, "starting OV6xx0 configuration"); /* Detect sensor (sub)type */ rc = i2c_r(sd, OV7610_REG_COM_I); @@ -1251,15 +1277,6 @@ static int ov6xx0_configure(struct sd *sd) /* Set sensor-specific vars */ sd->sif = 1; - if (sd->sensor == SEN_OV6620) { - PDEBUG(D_PROBE, "Writing 6x20 registers"); - if (write_i2c_regvals(sd, norm_6x20, ARRAY_SIZE(norm_6x20))) - return -1; - } else { - PDEBUG(D_PROBE, "Writing 6x30 registers"); - if (write_i2c_regvals(sd, norm_6x30, ARRAY_SIZE(norm_6x30))) - return -1; - } return 0; } @@ -1298,22 +1315,31 @@ static int sd_config(struct gspca_dev *gspca_dev, ov51x_led_control(sd, 0); /* turn LED off */ /* Test for 76xx */ - sd->primary_i2c_slave = OV7xx0_SID; if (ov51x_set_slave_ids(sd, OV7xx0_SID) < 0) goto error; /* The OV519 must be more aggressive about sensor detection since * I2C write will never fail if the sensor is not present. We have * to try to initialize the sensor to detect its presence */ - if (init_ov_sensor(sd) < 0) { + if (init_ov_sensor(sd) >= 0) { + if (ov7xx0_configure(sd) < 0) { + PDEBUG(D_ERR, "Failed to configure OV7xx0"); + goto error; + } + } else { + /* Test for 6xx0 */ - sd->primary_i2c_slave = OV6xx0_SID; if (ov51x_set_slave_ids(sd, OV6xx0_SID) < 0) goto error; - if (init_ov_sensor(sd) < 0) { + if (init_ov_sensor(sd) >= 0) { + if (ov6xx0_configure(sd) < 0) { + PDEBUG(D_ERR, "Failed to configure OV6xx0"); + goto error; + } + } else { + /* Test for 8xx0 */ - sd->primary_i2c_slave = OV8xx0_SID; if (ov51x_set_slave_ids(sd, OV8xx0_SID) < 0) goto error; @@ -1321,24 +1347,13 @@ static int sd_config(struct gspca_dev *gspca_dev, PDEBUG(D_ERR, "Can't determine sensor slave IDs"); goto error; - } else { - if (ov8xx0_configure(sd) < 0) { - PDEBUG(D_ERR, - "Failed to configure OV8xx0 sensor"); - goto error; - } } - } else { - if (ov6xx0_configure(sd) < 0) { - PDEBUG(D_ERR, "Failed to configure OV6xx0"); + if (ov8xx0_configure(sd) < 0) { + PDEBUG(D_ERR, + "Failed to configure OV8xx0 sensor"); goto error; } } - } else { - if (ov7xx0_configure(sd) < 0) { - PDEBUG(D_ERR, "Failed to configure OV7xx0"); - goto error; - } } cam = &gspca_dev->cam; @@ -1364,6 +1379,41 @@ error: /* this function is called at open time */ static int sd_open(struct gspca_dev *gspca_dev) { + struct sd *sd = (struct sd *) gspca_dev; + + /* initialize the sensor */ + switch (sd->sensor) { + case SEN_OV6620: + if (write_i2c_regvals(sd, norm_6x20, ARRAY_SIZE(norm_6x20))) + return -EIO; + break; + case SEN_OV6630: + if (write_i2c_regvals(sd, norm_6x30, ARRAY_SIZE(norm_6x30))) + return -EIO; + break; + default: +/* case SEN_OV7610: */ +/* case SEN_OV76BE: */ + if (write_i2c_regvals(sd, norm_7610, ARRAY_SIZE(norm_7610))) + return -EIO; + break; + case SEN_OV7620: + if (write_i2c_regvals(sd, norm_7620, ARRAY_SIZE(norm_7620))) + return -EIO; + break; + case SEN_OV7640: + if (write_i2c_regvals(sd, norm_7640, ARRAY_SIZE(norm_7640))) + return -EIO; + break; + case SEN_OV7670: + if (write_i2c_regvals(sd, norm_7670, ARRAY_SIZE(norm_7670))) + return -EIO; + break; + case SEN_OV8610: + if (write_i2c_regvals(sd, norm_8610, ARRAY_SIZE(norm_8610))) + return -EIO; + break; + } return 0; } -- cgit v0.10.2 From 66e4124f41808b50f6e1b6771621d6c7bf1c34a6 Mon Sep 17 00:00:00 2001 From: Jean-Francois Moine Date: Wed, 3 Sep 2008 17:12:16 -0300 Subject: V4L/DVB (8820): gspca: Change initialization and gamma of zc3xx - pas106. Signed-off-by: Jean-Francois Moine Signed-off-by: Mauro Carvalho Chehab diff --git a/drivers/media/video/gspca/pac207.c b/drivers/media/video/gspca/pac207.c index 620c963..e6b5c8a 100644 --- a/drivers/media/video/gspca/pac207.c +++ b/drivers/media/video/gspca/pac207.c @@ -131,7 +131,8 @@ static struct ctrl sd_ctrls[] = { .minimum = 0, .maximum = 1, .step = 1, - .default_value = 1, +#define AUTOGAIN_DEF 1 + .default_value = AUTOGAIN_DEF, .flags = 0, }, .set = sd_setautogain, @@ -256,13 +257,6 @@ static int sd_config(struct gspca_dev *gspca_dev, return -ENODEV; } - pac207_write_reg(gspca_dev, 0x41, 0x00); - /* Bit_0=Image Format, - * Bit_1=LED, - * Bit_2=Compression test mode enable */ - pac207_write_reg(gspca_dev, 0x0f, 0x00); /* Power Control */ - pac207_write_reg(gspca_dev, 0x11, 0x30); /* Analog Bias */ - PDEBUG(D_PROBE, "Pixart PAC207BCA Image Processor and Control Chip detected" " (vid/pid 0x%04X:0x%04X)", id->idVendor, id->idProduct); @@ -274,6 +268,7 @@ static int sd_config(struct gspca_dev *gspca_dev, sd->brightness = PAC207_BRIGHTNESS_DEFAULT; sd->exposure = PAC207_EXPOSURE_DEFAULT; sd->gain = PAC207_GAIN_DEFAULT; + sd->autogain = AUTOGAIN_DEF; return 0; } @@ -281,9 +276,13 @@ static int sd_config(struct gspca_dev *gspca_dev, /* this function is called at open time */ static int sd_open(struct gspca_dev *gspca_dev) { - struct sd *sd = (struct sd *) gspca_dev; + pac207_write_reg(gspca_dev, 0x41, 0x00); + /* Bit_0=Image Format, + * Bit_1=LED, + * Bit_2=Compression test mode enable */ + pac207_write_reg(gspca_dev, 0x0f, 0x00); /* Power Control */ + pac207_write_reg(gspca_dev, 0x11, 0x30); /* Analog Bias */ - sd->autogain = 1; return 0; } -- cgit v0.10.2 From 012d6b029ec17f45374303bbdccd0bc206725751 Mon Sep 17 00:00:00 2001 From: Jean-Francois Moine Date: Wed, 3 Sep 2008 17:12:16 -0300 Subject: V4L/DVB (8822): gspca: Change some subdriver functions for suspend/resume. - new function 'init' called on probe and resume - remove the functions 'open' and 'closed' - 'stopN' and 'stop0' are optional Signed-off-by: Jean-Francois Moine Signed-off-by: Mauro Carvalho Chehab diff --git a/drivers/media/video/gspca/conex.c b/drivers/media/video/gspca/conex.c index 739ef557..3db5c1e 100644 --- a/drivers/media/video/gspca/conex.c +++ b/drivers/media/video/gspca/conex.c @@ -826,8 +826,8 @@ static int sd_config(struct gspca_dev *gspca_dev, return 0; } -/* this function is called at open time */ -static int sd_open(struct gspca_dev *gspca_dev) +/* this function is called at probe and resume time */ +static int sd_init(struct gspca_dev *gspca_dev) { cx11646_init1(gspca_dev); cx11646_initsize(gspca_dev); @@ -845,10 +845,6 @@ static void sd_start(struct gspca_dev *gspca_dev) cx11646_jpeg(gspca_dev); } -static void sd_stopN(struct gspca_dev *gspca_dev) -{ -} - static void sd_stop0(struct gspca_dev *gspca_dev) { int retry = 50; @@ -871,10 +867,6 @@ static void sd_stop0(struct gspca_dev *gspca_dev) reg_w_val(gspca_dev, 0x00fc, 0xe0); } -static void sd_close(struct gspca_dev *gspca_dev) -{ -} - static void sd_pkt_scan(struct gspca_dev *gspca_dev, struct gspca_frame *frame, /* target */ __u8 *data, /* isoc packet */ @@ -998,11 +990,9 @@ static struct sd_desc sd_desc = { .ctrls = sd_ctrls, .nctrls = ARRAY_SIZE(sd_ctrls), .config = sd_config, - .open = sd_open, + .init = sd_init, .start = sd_start, - .stopN = sd_stopN, .stop0 = sd_stop0, - .close = sd_close, .pkt_scan = sd_pkt_scan, }; diff --git a/drivers/media/video/gspca/etoms.c b/drivers/media/video/gspca/etoms.c index e5a9eee..c03b1f4 100644 --- a/drivers/media/video/gspca/etoms.c +++ b/drivers/media/video/gspca/etoms.c @@ -676,8 +676,8 @@ static int sd_config(struct gspca_dev *gspca_dev, return 0; } -/* this function is called at open time */ -static int sd_open(struct gspca_dev *gspca_dev) +/* this function is called at probe and resume time */ +static int sd_init(struct gspca_dev *gspca_dev) { struct sd *sd = (struct sd *) gspca_dev; @@ -711,14 +711,6 @@ static void sd_stopN(struct gspca_dev *gspca_dev) et_video(gspca_dev, 0); /* video off */ } -static void sd_stop0(struct gspca_dev *gspca_dev) -{ -} - -static void sd_close(struct gspca_dev *gspca_dev) -{ -} - static __u8 Et_getgainG(struct gspca_dev *gspca_dev) { struct sd *sd = (struct sd *) gspca_dev; @@ -895,11 +887,9 @@ static struct sd_desc sd_desc = { .ctrls = sd_ctrls, .nctrls = ARRAY_SIZE(sd_ctrls), .config = sd_config, - .open = sd_open, + .init = sd_init, .start = sd_start, .stopN = sd_stopN, - .stop0 = sd_stop0, - .close = sd_close, .pkt_scan = sd_pkt_scan, .dq_callback = do_autogain, }; diff --git a/drivers/media/video/gspca/gspca.c b/drivers/media/video/gspca/gspca.c index 1767991..fe096e7 100644 --- a/drivers/media/video/gspca/gspca.c +++ b/drivers/media/video/gspca/gspca.c @@ -558,10 +558,12 @@ static void gspca_stream_off(struct gspca_dev *gspca_dev) gspca_dev->streaming = 0; atomic_set(&gspca_dev->nevent, 0); if (gspca_dev->present) { - gspca_dev->sd_desc->stopN(gspca_dev); + if (gspca_dev->sd_desc->stopN) + gspca_dev->sd_desc->stopN(gspca_dev); destroy_urbs(gspca_dev); gspca_set_alt0(gspca_dev); - gspca_dev->sd_desc->stop0(gspca_dev); + if (gspca_dev->sd_desc->stop0) + gspca_dev->sd_desc->stop0(gspca_dev); PDEBUG(D_STREAM, "stream off OK"); } } @@ -770,19 +772,7 @@ static int dev_open(struct inode *inode, struct file *file) goto out; } - /* if not done yet, initialize the sensor */ - if (gspca_dev->users == 0) { - if (mutex_lock_interruptible(&gspca_dev->usb_lock)) { - ret = -ERESTARTSYS; - goto out; - } - ret = gspca_dev->sd_desc->open(gspca_dev); - mutex_unlock(&gspca_dev->usb_lock); - if (ret != 0) { - PDEBUG(D_ERR|D_CONF, "init device failed %d", ret); - goto out; - } - } else if (gspca_dev->users > 4) { /* (arbitrary value) */ + if (gspca_dev->users > 4) { /* (arbitrary value) */ ret = -EBUSY; goto out; } @@ -795,6 +785,7 @@ static int dev_open(struct inode *inode, struct file *file) else gspca_dev->vdev.debug &= ~3; #endif + ret = 0; out: mutex_unlock(&gspca_dev->queue_lock); if (ret != 0) @@ -815,11 +806,6 @@ static int dev_close(struct inode *inode, struct file *file) /* if the file did the capture, free the streaming resources */ if (gspca_dev->capt_file == file) { - mutex_lock(&gspca_dev->usb_lock); - if (gspca_dev->streaming) - gspca_stream_off(gspca_dev); - gspca_dev->sd_desc->close(gspca_dev); - mutex_unlock(&gspca_dev->usb_lock); frame_free(gspca_dev); gspca_dev->capt_file = NULL; gspca_dev->memory = GSPCA_MEMORY_NO; @@ -1747,10 +1733,13 @@ int gspca_dev_probe(struct usb_interface *intf, /* gspca_dev->users = 0; (done by kzalloc) */ gspca_dev->nbufread = 2; - /* configure the subdriver */ + /* configure the subdriver and initialize the USB device */ ret = gspca_dev->sd_desc->config(gspca_dev, id); if (ret < 0) goto out; + ret = gspca_dev->sd_desc->init(gspca_dev); + if (ret < 0) + goto out; ret = gspca_set_alt0(gspca_dev); if (ret < 0) goto out; @@ -1825,10 +1814,12 @@ int gspca_suspend(struct usb_interface *intf, pm_message_t message) if (!gspca_dev->streaming) return 0; gspca_dev->frozen = 1; /* avoid urb error messages */ - gspca_dev->sd_desc->stopN(gspca_dev); + if (gspca_dev->sd_desc->stopN) + gspca_dev->sd_desc->stopN(gspca_dev); destroy_urbs(gspca_dev); gspca_set_alt0(gspca_dev); - gspca_dev->sd_desc->stop0(gspca_dev); + if (gspca_dev->sd_desc->stop0) + gspca_dev->sd_desc->stop0(gspca_dev); return 0; } EXPORT_SYMBOL(gspca_suspend); @@ -1838,11 +1829,9 @@ int gspca_resume(struct usb_interface *intf) struct gspca_dev *gspca_dev = usb_get_intfdata(intf); gspca_dev->frozen = 0; - if (gspca_dev->users != 0) { - gspca_dev->sd_desc->open(gspca_dev); - if (gspca_dev->streaming) - return gspca_init_transfer(gspca_dev); - } + gspca_dev->sd_desc->init(gspca_dev); + if (gspca_dev->streaming) + return gspca_init_transfer(gspca_dev); return 0; } EXPORT_SYMBOL(gspca_resume); diff --git a/drivers/media/video/gspca/gspca.h b/drivers/media/video/gspca/gspca.h index a804ef1..7c2f44b2 100644 --- a/drivers/media/video/gspca/gspca.h +++ b/drivers/media/video/gspca/gspca.h @@ -90,15 +90,14 @@ struct sd_desc { /* controls */ const struct ctrl *ctrls; int nctrls; -/* operations */ +/* mandatory operations */ cam_cf_op config; /* called on probe */ - cam_op open; /* called on open */ + cam_op init; /* called on probe and resume */ cam_v_op start; /* called on stream on */ - cam_v_op stopN; /* called on stream off - main alt */ - cam_v_op stop0; /* called on stream off - alt 0 */ - cam_v_op close; /* called on close */ cam_pkt_op pkt_scan; /* optional operations */ + cam_v_op stopN; /* called on stream off - main alt */ + cam_v_op stop0; /* called on stream off - alt 0 */ cam_v_op dq_callback; /* called when a frame has been dequeued */ cam_jpg_op get_jcomp; cam_jpg_op set_jcomp; diff --git a/drivers/media/video/gspca/mars.c b/drivers/media/video/gspca/mars.c index d7e2095..2814759 100644 --- a/drivers/media/video/gspca/mars.c +++ b/drivers/media/video/gspca/mars.c @@ -144,8 +144,8 @@ static int sd_config(struct gspca_dev *gspca_dev, return 0; } -/* this function is called at open time */ -static int sd_open(struct gspca_dev *gspca_dev) +/* this function is called at probe and resume time */ +static int sd_init(struct gspca_dev *gspca_dev) { return 0; } @@ -358,14 +358,6 @@ static void sd_stopN(struct gspca_dev *gspca_dev) PDEBUG(D_ERR, "Camera Stop failed"); } -static void sd_stop0(struct gspca_dev *gspca_dev) -{ -} - -static void sd_close(struct gspca_dev *gspca_dev) -{ -} - static void sd_pkt_scan(struct gspca_dev *gspca_dev, struct gspca_frame *frame, /* target */ __u8 *data, /* isoc packet */ @@ -411,11 +403,9 @@ static const struct sd_desc sd_desc = { .ctrls = sd_ctrls, .nctrls = ARRAY_SIZE(sd_ctrls), .config = sd_config, - .open = sd_open, + .init = sd_init, .start = sd_start, .stopN = sd_stopN, - .stop0 = sd_stop0, - .close = sd_close, .pkt_scan = sd_pkt_scan, }; diff --git a/drivers/media/video/gspca/ov519.c b/drivers/media/video/gspca/ov519.c index 4062aed..19378dd 100644 --- a/drivers/media/video/gspca/ov519.c +++ b/drivers/media/video/gspca/ov519.c @@ -1376,8 +1376,8 @@ error: return -EBUSY; } -/* this function is called at open time */ -static int sd_open(struct gspca_dev *gspca_dev) +/* this function is called at probe and resume time */ +static int sd_init(struct gspca_dev *gspca_dev) { struct sd *sd = (struct sd *) gspca_dev; @@ -1877,14 +1877,6 @@ static void sd_stopN(struct gspca_dev *gspca_dev) ov51x_led_control((struct sd *) gspca_dev, 0); } -static void sd_stop0(struct gspca_dev *gspca_dev) -{ -} - -static void sd_close(struct gspca_dev *gspca_dev) -{ -} - static void sd_pkt_scan(struct gspca_dev *gspca_dev, struct gspca_frame *frame, /* target */ __u8 *data, /* isoc packet */ @@ -2141,11 +2133,9 @@ static const struct sd_desc sd_desc = { .ctrls = sd_ctrls, .nctrls = ARRAY_SIZE(sd_ctrls), .config = sd_config, - .open = sd_open, + .init = sd_init, .start = sd_start, .stopN = sd_stopN, - .stop0 = sd_stop0, - .close = sd_close, .pkt_scan = sd_pkt_scan, }; diff --git a/drivers/media/video/gspca/pac207.c b/drivers/media/video/gspca/pac207.c index e6b5c8a..a15bcca 100644 --- a/drivers/media/video/gspca/pac207.c +++ b/drivers/media/video/gspca/pac207.c @@ -273,8 +273,8 @@ static int sd_config(struct gspca_dev *gspca_dev, return 0; } -/* this function is called at open time */ -static int sd_open(struct gspca_dev *gspca_dev) +/* this function is called at probe and resume time */ +static int sd_init(struct gspca_dev *gspca_dev) { pac207_write_reg(gspca_dev, 0x41, 0x00); /* Bit_0=Image Format, @@ -338,15 +338,6 @@ static void sd_stopN(struct gspca_dev *gspca_dev) pac207_write_reg(gspca_dev, 0x0f, 0x00); /* Power Control */ } -static void sd_stop0(struct gspca_dev *gspca_dev) -{ -} - -/* this function is called at close time */ -static void sd_close(struct gspca_dev *gspca_dev) -{ -} - static void pac207_do_auto_gain(struct gspca_dev *gspca_dev) { struct sd *sd = (struct sd *) gspca_dev; @@ -532,11 +523,9 @@ static const struct sd_desc sd_desc = { .ctrls = sd_ctrls, .nctrls = ARRAY_SIZE(sd_ctrls), .config = sd_config, - .open = sd_open, + .init = sd_init, .start = sd_start, .stopN = sd_stopN, - .stop0 = sd_stop0, - .close = sd_close, .dq_callback = pac207_do_auto_gain, .pkt_scan = sd_pkt_scan, }; diff --git a/drivers/media/video/gspca/pac7311.c b/drivers/media/video/gspca/pac7311.c index 69d6100..e22ca61 100644 --- a/drivers/media/video/gspca/pac7311.c +++ b/drivers/media/video/gspca/pac7311.c @@ -590,8 +590,8 @@ static void sethvflip(struct gspca_dev *gspca_dev) reg_w(gspca_dev, 0x11, 0x01); } -/* this function is called at open time */ -static int sd_open(struct gspca_dev *gspca_dev) +/* this function is called at probe and resume time */ +static int sd_init(struct gspca_dev *gspca_dev) { return 0; } @@ -691,11 +691,6 @@ static void sd_stop0(struct gspca_dev *gspca_dev) } } -/* this function is called at close time */ -static void sd_close(struct gspca_dev *gspca_dev) -{ -} - static void do_autogain(struct gspca_dev *gspca_dev) { } @@ -902,11 +897,10 @@ static struct sd_desc sd_desc = { .ctrls = sd_ctrls, .nctrls = ARRAY_SIZE(sd_ctrls), .config = sd_config, - .open = sd_open, + .init = sd_init, .start = sd_start, .stopN = sd_stopN, .stop0 = sd_stop0, - .close = sd_close, .pkt_scan = sd_pkt_scan, .dq_callback = do_autogain, }; diff --git a/drivers/media/video/gspca/sonixb.c b/drivers/media/video/gspca/sonixb.c index 64aae06..044a9ec 100644 --- a/drivers/media/video/gspca/sonixb.c +++ b/drivers/media/video/gspca/sonixb.c @@ -799,8 +799,8 @@ static int sd_config(struct gspca_dev *gspca_dev, return 0; } -/* this function is called at open time */ -static int sd_open(struct gspca_dev *gspca_dev) +/* this function is called at probe and resume time */ +static int sd_init(struct gspca_dev *gspca_dev) { return 0; } @@ -963,14 +963,6 @@ static void sd_stopN(struct gspca_dev *gspca_dev) reg_w(gspca_dev, 0x01, &ByteSend, 1); } -static void sd_stop0(struct gspca_dev *gspca_dev) -{ -} - -static void sd_close(struct gspca_dev *gspca_dev) -{ -} - static void sd_pkt_scan(struct gspca_dev *gspca_dev, struct gspca_frame *frame, /* target */ unsigned char *data, /* isoc packet */ @@ -1162,11 +1154,9 @@ static const struct sd_desc sd_desc = { .ctrls = sd_ctrls, .nctrls = ARRAY_SIZE(sd_ctrls), .config = sd_config, - .open = sd_open, + .init = sd_init, .start = sd_start, .stopN = sd_stopN, - .stop0 = sd_stop0, - .close = sd_close, .pkt_scan = sd_pkt_scan, .querymenu = sd_querymenu, .dq_callback = do_autogain, diff --git a/drivers/media/video/gspca/sonixj.c b/drivers/media/video/gspca/sonixj.c index e657b8b..5380b43 100644 --- a/drivers/media/video/gspca/sonixj.c +++ b/drivers/media/video/gspca/sonixj.c @@ -948,8 +948,8 @@ static int sd_config(struct gspca_dev *gspca_dev, return 0; } -/* this function is called at open time */ -static int sd_open(struct gspca_dev *gspca_dev) +/* this function is called at probe and resume time */ +static int sd_init(struct gspca_dev *gspca_dev) { struct sd *sd = (struct sd *) gspca_dev; /* const __u8 *sn9c1xx; */ @@ -1353,14 +1353,6 @@ static void sd_stopN(struct gspca_dev *gspca_dev) reg_w1(gspca_dev, 0xf1, 0x00); } -static void sd_stop0(struct gspca_dev *gspca_dev) -{ -} - -static void sd_close(struct gspca_dev *gspca_dev) -{ -} - static void do_autogain(struct gspca_dev *gspca_dev) { struct sd *sd = (struct sd *) gspca_dev; @@ -1548,11 +1540,9 @@ static const struct sd_desc sd_desc = { .ctrls = sd_ctrls, .nctrls = ARRAY_SIZE(sd_ctrls), .config = sd_config, - .open = sd_open, + .init = sd_init, .start = sd_start, .stopN = sd_stopN, - .stop0 = sd_stop0, - .close = sd_close, .pkt_scan = sd_pkt_scan, .dq_callback = do_autogain, }; diff --git a/drivers/media/video/gspca/spca500.c b/drivers/media/video/gspca/spca500.c index 5a20385fb..6e73390 100644 --- a/drivers/media/video/gspca/spca500.c +++ b/drivers/media/video/gspca/spca500.c @@ -645,8 +645,8 @@ static int sd_config(struct gspca_dev *gspca_dev, return 0; } -/* this function is called at open time */ -static int sd_open(struct gspca_dev *gspca_dev) +/* this function is called at probe and resume time */ +static int sd_init(struct gspca_dev *gspca_dev) { struct sd *sd = (struct sd *) gspca_dev; @@ -880,14 +880,6 @@ static void sd_stopN(struct gspca_dev *gspca_dev) gspca_dev->usb_buf[0]); } -static void sd_stop0(struct gspca_dev *gspca_dev) -{ -} - -static void sd_close(struct gspca_dev *gspca_dev) -{ -} - static void sd_pkt_scan(struct gspca_dev *gspca_dev, struct gspca_frame *frame, /* target */ __u8 *data, /* isoc packet */ @@ -1051,11 +1043,9 @@ static struct sd_desc sd_desc = { .ctrls = sd_ctrls, .nctrls = ARRAY_SIZE(sd_ctrls), .config = sd_config, - .open = sd_open, + .init = sd_init, .start = sd_start, .stopN = sd_stopN, - .stop0 = sd_stop0, - .close = sd_close, .pkt_scan = sd_pkt_scan, }; diff --git a/drivers/media/video/gspca/spca501.c b/drivers/media/video/gspca/spca501.c index 525f1b3..e9eb59b 100644 --- a/drivers/media/video/gspca/spca501.c +++ b/drivers/media/video/gspca/spca501.c @@ -1953,8 +1953,8 @@ error: return -EINVAL; } -/* this function is called at open time */ -static int sd_open(struct gspca_dev *gspca_dev) +/* this function is called at probe and resume time */ +static int sd_init(struct gspca_dev *gspca_dev) { struct sd *sd = (struct sd *) gspca_dev; @@ -2023,11 +2023,6 @@ static void sd_stopN(struct gspca_dev *gspca_dev) static void sd_stop0(struct gspca_dev *gspca_dev) { -} - -/* this function is called at close time */ -static void sd_close(struct gspca_dev *gspca_dev) -{ reg_write(gspca_dev->dev, SPCA501_REG_CTLRL, 0x05, 0x00); } @@ -2120,11 +2115,10 @@ static const struct sd_desc sd_desc = { .ctrls = sd_ctrls, .nctrls = ARRAY_SIZE(sd_ctrls), .config = sd_config, - .open = sd_open, + .init = sd_init, .start = sd_start, .stopN = sd_stopN, .stop0 = sd_stop0, - .close = sd_close, .pkt_scan = sd_pkt_scan, }; diff --git a/drivers/media/video/gspca/spca505.c b/drivers/media/video/gspca/spca505.c index 8f00558..f601daf 100644 --- a/drivers/media/video/gspca/spca505.c +++ b/drivers/media/video/gspca/spca505.c @@ -655,8 +655,8 @@ static int sd_config(struct gspca_dev *gspca_dev, return 0; } -/* this function is called at open time */ -static int sd_open(struct gspca_dev *gspca_dev) +/* this function is called at probe and resume time */ +static int sd_init(struct gspca_dev *gspca_dev) { struct sd *sd = (struct sd *) gspca_dev; int ret; @@ -743,11 +743,6 @@ static void sd_stopN(struct gspca_dev *gspca_dev) static void sd_stop0(struct gspca_dev *gspca_dev) { -} - -/* this function is called at close time */ -static void sd_close(struct gspca_dev *gspca_dev) -{ /* This maybe reset or power control */ reg_write(gspca_dev->dev, 0x03, 0x03, 0x20); reg_write(gspca_dev->dev, 0x03, 0x01, 0x0); @@ -825,11 +820,10 @@ static const struct sd_desc sd_desc = { .ctrls = sd_ctrls, .nctrls = ARRAY_SIZE(sd_ctrls), .config = sd_config, - .open = sd_open, + .init = sd_init, .start = sd_start, .stopN = sd_stopN, .stop0 = sd_stop0, - .close = sd_close, .pkt_scan = sd_pkt_scan, }; diff --git a/drivers/media/video/gspca/spca506.c b/drivers/media/video/gspca/spca506.c index ae77248..195dce9 100644 --- a/drivers/media/video/gspca/spca506.c +++ b/drivers/media/video/gspca/spca506.c @@ -313,8 +313,8 @@ static int sd_config(struct gspca_dev *gspca_dev, return 0; } -/* this function is called at open time */ -static int sd_open(struct gspca_dev *gspca_dev) +/* this function is called at probe and resume time */ +static int sd_init(struct gspca_dev *gspca_dev) { struct usb_device *dev = gspca_dev->dev; @@ -560,14 +560,6 @@ static void sd_stopN(struct gspca_dev *gspca_dev) reg_w(dev, 0x03, 0x00, 0x0003); } -static void sd_stop0(struct gspca_dev *gspca_dev) -{ -} - -static void sd_close(struct gspca_dev *gspca_dev) -{ -} - static void sd_pkt_scan(struct gspca_dev *gspca_dev, struct gspca_frame *frame, /* target */ __u8 *data, /* isoc packet */ @@ -740,11 +732,9 @@ static struct sd_desc sd_desc = { .ctrls = sd_ctrls, .nctrls = ARRAY_SIZE(sd_ctrls), .config = sd_config, - .open = sd_open, + .init = sd_init, .start = sd_start, .stopN = sd_stopN, - .stop0 = sd_stop0, - .close = sd_close, .pkt_scan = sd_pkt_scan, }; diff --git a/drivers/media/video/gspca/spca508.c b/drivers/media/video/gspca/spca508.c index 7b38c4e..281ce02 100644 --- a/drivers/media/video/gspca/spca508.c +++ b/drivers/media/video/gspca/spca508.c @@ -1521,8 +1521,8 @@ static int sd_config(struct gspca_dev *gspca_dev, return 0; /* success */ } -/* this function is called at open time */ -static int sd_open(struct gspca_dev *gspca_dev) +/* this function is called at probe and resume time */ +static int sd_init(struct gspca_dev *gspca_dev) { /* write_vector(gspca_dev, spca508_open_data); */ return 0; @@ -1554,15 +1554,6 @@ static void sd_stopN(struct gspca_dev *gspca_dev) reg_write(gspca_dev->dev, 0x8112, 0x20); } -static void sd_stop0(struct gspca_dev *gspca_dev) -{ -} - -/* this function is called at close time */ -static void sd_close(struct gspca_dev *gspca_dev) -{ -} - static void sd_pkt_scan(struct gspca_dev *gspca_dev, struct gspca_frame *frame, /* target */ __u8 *data, /* isoc packet */ @@ -1633,11 +1624,9 @@ static const struct sd_desc sd_desc = { .ctrls = sd_ctrls, .nctrls = ARRAY_SIZE(sd_ctrls), .config = sd_config, - .open = sd_open, + .init = sd_init, .start = sd_start, .stopN = sd_stopN, - .stop0 = sd_stop0, - .close = sd_close, .pkt_scan = sd_pkt_scan, }; diff --git a/drivers/media/video/gspca/spca561.c b/drivers/media/video/gspca/spca561.c index b6a013f..2ca509d 100644 --- a/drivers/media/video/gspca/spca561.c +++ b/drivers/media/video/gspca/spca561.c @@ -560,14 +560,14 @@ static int sd_config(struct gspca_dev *gspca_dev, return 0; } -/* this function is called at open time */ -static int sd_open_12a(struct gspca_dev *gspca_dev) +/* this function is called at probe and resume time */ +static int sd_init_12a(struct gspca_dev *gspca_dev) { PDEBUG(D_STREAM, "Chip revision: 012a"); init_161rev12A(gspca_dev); return 0; } -static int sd_open_72a(struct gspca_dev *gspca_dev) +static int sd_init_72a(struct gspca_dev *gspca_dev) { PDEBUG(D_STREAM, "Chip revision: 072a"); write_vector(gspca_dev, spca561_init_data); @@ -733,12 +733,7 @@ static void sd_stop0(struct gspca_dev *gspca_dev) reg_w_val(gspca_dev->dev, 0x8118, 0x29); reg_w_val(gspca_dev->dev, 0x8114, 0x08); } -} - -/* this function is called at close time */ -static void sd_close(struct gspca_dev *gspca_dev) -{ - reg_w_val(gspca_dev->dev, 0x8114, 0); +/* reg_w_val(gspca_dev->dev, 0x8114, 0); */ } static void do_autogain(struct gspca_dev *gspca_dev) @@ -1121,11 +1116,10 @@ static const struct sd_desc sd_desc_12a = { .ctrls = sd_ctrls_12a, .nctrls = ARRAY_SIZE(sd_ctrls_12a), .config = sd_config, - .open = sd_open_12a, + .init = sd_init_12a, .start = sd_start_12a, .stopN = sd_stopN, .stop0 = sd_stop0, - .close = sd_close, .pkt_scan = sd_pkt_scan, /* .dq_callback = do_autogain, * fixme */ }; @@ -1134,11 +1128,10 @@ static const struct sd_desc sd_desc_72a = { .ctrls = sd_ctrls_72a, .nctrls = ARRAY_SIZE(sd_ctrls_72a), .config = sd_config, - .open = sd_open_72a, + .init = sd_init_72a, .start = sd_start_72a, .stopN = sd_stopN, .stop0 = sd_stop0, - .close = sd_close, .pkt_scan = sd_pkt_scan, .dq_callback = do_autogain, }; diff --git a/drivers/media/video/gspca/stk014.c b/drivers/media/video/gspca/stk014.c index 387a8cf..2f2de42 100644 --- a/drivers/media/video/gspca/stk014.c +++ b/drivers/media/video/gspca/stk014.c @@ -306,8 +306,8 @@ static int sd_config(struct gspca_dev *gspca_dev, return 0; } -/* this function is called at open time */ -static int sd_open(struct gspca_dev *gspca_dev) +/* this function is called at probe and resume time */ +static int sd_init(struct gspca_dev *gspca_dev) { int ret; @@ -398,14 +398,6 @@ static void sd_stopN(struct gspca_dev *gspca_dev) PDEBUG(D_STREAM, "camera stopped"); } -static void sd_stop0(struct gspca_dev *gspca_dev) -{ -} - -static void sd_close(struct gspca_dev *gspca_dev) -{ -} - static void sd_pkt_scan(struct gspca_dev *gspca_dev, struct gspca_frame *frame, /* target */ __u8 *data, /* isoc packet */ @@ -535,11 +527,9 @@ static const struct sd_desc sd_desc = { .ctrls = sd_ctrls, .nctrls = ARRAY_SIZE(sd_ctrls), .config = sd_config, - .open = sd_open, + .init = sd_init, .start = sd_start, .stopN = sd_stopN, - .stop0 = sd_stop0, - .close = sd_close, .pkt_scan = sd_pkt_scan, .querymenu = sd_querymenu, }; diff --git a/drivers/media/video/gspca/sunplus.c b/drivers/media/video/gspca/sunplus.c index c935384..bddf733 100644 --- a/drivers/media/video/gspca/sunplus.c +++ b/drivers/media/video/gspca/sunplus.c @@ -848,8 +848,8 @@ static int sd_config(struct gspca_dev *gspca_dev, return 0; } -/* this function is called at open time */ -static int sd_open(struct gspca_dev *gspca_dev) +/* this function is called at probe and resume time */ +static int sd_init(struct gspca_dev *gspca_dev) { struct sd *sd = (struct sd *) gspca_dev; struct usb_device *dev = gspca_dev->dev; @@ -1069,14 +1069,6 @@ static void sd_stopN(struct gspca_dev *gspca_dev) } } -static void sd_stop0(struct gspca_dev *gspca_dev) -{ -} - -static void sd_close(struct gspca_dev *gspca_dev) -{ -} - static void sd_pkt_scan(struct gspca_dev *gspca_dev, struct gspca_frame *frame, /* target */ __u8 *data, /* isoc packet */ @@ -1369,11 +1361,9 @@ static const struct sd_desc sd_desc = { .ctrls = sd_ctrls, .nctrls = ARRAY_SIZE(sd_ctrls), .config = sd_config, - .open = sd_open, + .init = sd_init, .start = sd_start, .stopN = sd_stopN, - .stop0 = sd_stop0, - .close = sd_close, .pkt_scan = sd_pkt_scan, }; diff --git a/drivers/media/video/gspca/t613.c b/drivers/media/video/gspca/t613.c index 962c1df..81b175e 100644 --- a/drivers/media/video/gspca/t613.c +++ b/drivers/media/video/gspca/t613.c @@ -552,6 +552,13 @@ static int init_default_parameters(struct gspca_dev *gspca_dev) return 0; } +/* this function is called at probe and resume time */ +static int sd_init(struct gspca_dev *gspca_dev) +{ + init_default_parameters(gspca_dev); + return 0; +} + static void setbrightness(struct gspca_dev *gspca_dev) { struct sd *sd = (struct sd *) gspca_dev; @@ -893,18 +900,6 @@ static void sd_start(struct gspca_dev *gspca_dev) setcolors(gspca_dev); } -static void sd_stopN(struct gspca_dev *gspca_dev) -{ -} - -static void sd_stop0(struct gspca_dev *gspca_dev) -{ -} - -static void sd_close(struct gspca_dev *gspca_dev) -{ -} - static void sd_pkt_scan(struct gspca_dev *gspca_dev, struct gspca_frame *frame, /* target */ __u8 *data, /* isoc packet */ @@ -972,24 +967,14 @@ static int sd_querymenu(struct gspca_dev *gspca_dev, return -EINVAL; } -/* this function is called at open time */ -static int sd_open(struct gspca_dev *gspca_dev) -{ - init_default_parameters(gspca_dev); - return 0; -} - /* sub-driver description */ static const struct sd_desc sd_desc = { .name = MODULE_NAME, .ctrls = sd_ctrls, .nctrls = ARRAY_SIZE(sd_ctrls), .config = sd_config, - .open = sd_open, + .init = sd_init, .start = sd_start, - .stopN = sd_stopN, - .stop0 = sd_stop0, - .close = sd_close, .pkt_scan = sd_pkt_scan, .querymenu = sd_querymenu, }; diff --git a/drivers/media/video/gspca/tv8532.c b/drivers/media/video/gspca/tv8532.c index d227362..084af05 100644 --- a/drivers/media/video/gspca/tv8532.c +++ b/drivers/media/video/gspca/tv8532.c @@ -331,8 +331,8 @@ static void tv_8532_PollReg(struct gspca_dev *gspca_dev) } } -/* this function is called at open time */ -static int sd_open(struct gspca_dev *gspca_dev) +/* this function is called at probe and resume time */ +static int sd_init(struct gspca_dev *gspca_dev) { reg_w_1(gspca_dev, TV8532_AD_SLOPE, 0x32); reg_w_1(gspca_dev, TV8532_AD_BITCTRL, 0x00); @@ -450,14 +450,6 @@ static void sd_stopN(struct gspca_dev *gspca_dev) reg_w_1(gspca_dev, TV8532_GPIO_OE, 0x0b); } -static void sd_stop0(struct gspca_dev *gspca_dev) -{ -} - -static void sd_close(struct gspca_dev *gspca_dev) -{ -} - static void tv8532_preprocess(struct gspca_dev *gspca_dev) { struct sd *sd = (struct sd *) gspca_dev; @@ -611,11 +603,9 @@ static const struct sd_desc sd_desc = { .ctrls = sd_ctrls, .nctrls = ARRAY_SIZE(sd_ctrls), .config = sd_config, - .open = sd_open, + .init = sd_init, .start = sd_start, .stopN = sd_stopN, - .stop0 = sd_stop0, - .close = sd_close, .pkt_scan = sd_pkt_scan, }; diff --git a/drivers/media/video/gspca/vc032x.c b/drivers/media/video/gspca/vc032x.c index 5454f0e..f8c3ff3 100644 --- a/drivers/media/video/gspca/vc032x.c +++ b/drivers/media/video/gspca/vc032x.c @@ -1477,8 +1477,8 @@ static int sd_config(struct gspca_dev *gspca_dev, return 0; } -/* this function is called at open time */ -static int sd_open(struct gspca_dev *gspca_dev) +/* this function is called at probe and time */ +static int sd_init(struct gspca_dev *gspca_dev) { return 0; } @@ -1640,19 +1640,6 @@ static void sd_stop0(struct gspca_dev *gspca_dev) reg_w(dev, 0x89, 0xffff, 0xffff); } -/* this function is called at close time */ -static void sd_close(struct gspca_dev *gspca_dev) -{ -/* struct usb_device *dev = gspca_dev->dev; - __u8 buffread; - - reg_w(dev, 0x89, 0xffff, 0xffff); - reg_w(dev, 0xa0, 0x01, 0xb301); - reg_w(dev, 0xa0, 0x09, 0xb303); - reg_w(dev, 0x89, 0xffff, 0xffff); -*/ -} - static void sd_pkt_scan(struct gspca_dev *gspca_dev, struct gspca_frame *frame, /* target */ __u8 *data, /* isoc packet */ @@ -1741,11 +1728,10 @@ static const struct sd_desc sd_desc = { .ctrls = sd_ctrls, .nctrls = ARRAY_SIZE(sd_ctrls), .config = sd_config, - .open = sd_open, + .init = sd_init, .start = sd_start, .stopN = sd_stopN, .stop0 = sd_stop0, - .close = sd_close, .pkt_scan = sd_pkt_scan, .querymenu = sd_querymenu, }; diff --git a/drivers/media/video/gspca/zc3xx.c b/drivers/media/video/gspca/zc3xx.c index e78b9b7..f4239b4 100644 --- a/drivers/media/video/gspca/zc3xx.c +++ b/drivers/media/video/gspca/zc3xx.c @@ -7171,8 +7171,8 @@ static int sd_config(struct gspca_dev *gspca_dev, return 0; } -/* this function is called at open time */ -static int sd_open(struct gspca_dev *gspca_dev) +/* this function is called at probe and resume time */ +static int sd_init(struct gspca_dev *gspca_dev) { reg_w(gspca_dev->dev, 0x01, 0x0000); return 0; @@ -7333,10 +7333,6 @@ static void sd_start(struct gspca_dev *gspca_dev) } } -static void sd_stopN(struct gspca_dev *gspca_dev) -{ -} - static void sd_stop0(struct gspca_dev *gspca_dev) { struct sd *sd = (struct sd *) gspca_dev; @@ -7344,11 +7340,6 @@ static void sd_stop0(struct gspca_dev *gspca_dev) send_unknown(gspca_dev->dev, sd->sensor); } -/* this function is called at close time */ -static void sd_close(struct gspca_dev *gspca_dev) -{ -} - static void sd_pkt_scan(struct gspca_dev *gspca_dev, struct gspca_frame *frame, __u8 *data, @@ -7508,11 +7499,9 @@ static const struct sd_desc sd_desc = { .ctrls = sd_ctrls, .nctrls = sizeof sd_ctrls / sizeof sd_ctrls[0], .config = sd_config, - .open = sd_open, + .init = sd_init, .start = sd_start, - .stopN = sd_stopN, .stop0 = sd_stop0, - .close = sd_close, .pkt_scan = sd_pkt_scan, .querymenu = sd_querymenu, }; -- cgit v0.10.2 From de00448f708a2fd705f9c5ccdfa383dbf3dcef92 Mon Sep 17 00:00:00 2001 From: Jean-Francois Moine Date: Wed, 3 Sep 2008 17:12:16 -0300 Subject: V4L/DVB (8823): gspca: H and V flips work for ov7670 only in ov519. Signed-off-by: Jean-Francois Moine Signed-off-by: Mauro Carvalho Chehab diff --git a/drivers/media/video/gspca/ov519.c b/drivers/media/video/gspca/ov519.c index 19378dd..4df4eec 100644 --- a/drivers/media/video/gspca/ov519.c +++ b/drivers/media/video/gspca/ov519.c @@ -126,6 +126,7 @@ static struct ctrl sd_ctrls[] = { .get = sd_getcolors, }, /* next controls work with ov7670 only */ +#define HFLIP_IDX 3 { { .id = V4L2_CID_HFLIP, @@ -140,6 +141,7 @@ static struct ctrl sd_ctrls[] = { .set = sd_sethflip, .get = sd_gethflip, }, +#define VFLIP_IDX 4 { { .id = V4L2_CID_VFLIP, @@ -1370,6 +1372,9 @@ static int sd_config(struct gspca_dev *gspca_dev, sd->colors = COLOR_DEF; sd->hflip = HFLIP_DEF; sd->vflip = VFLIP_DEF; + if (sd->sensor != SEN_OV7670) + gspca_dev->ctrl_dis = (1 << HFLIP_IDX) + | (1 << VFLIP_IDX); return 0; error: PDEBUG(D_ERR, "OV519 Config failed"); -- cgit v0.10.2 From a1e8288b1d80130119692818b46694660f28e03a Mon Sep 17 00:00:00 2001 From: Jean-Francois Moine Date: Wed, 3 Sep 2008 17:12:17 -0300 Subject: V4L/DVB (8824): gspca: Too much code removed in the suspend/resume changeset. - the stream must stop when the main application closes the device. Signed-off-by: Jean-Francois Moine Signed-off-by: Mauro Carvalho Chehab diff --git a/drivers/media/video/gspca/gspca.c b/drivers/media/video/gspca/gspca.c index fe096e7..42b0b83 100644 --- a/drivers/media/video/gspca/gspca.c +++ b/drivers/media/video/gspca/gspca.c @@ -806,6 +806,11 @@ static int dev_close(struct inode *inode, struct file *file) /* if the file did the capture, free the streaming resources */ if (gspca_dev->capt_file == file) { + if (gspca_dev->streaming) { + mutex_lock(&gspca_dev->usb_lock); + gspca_stream_off(gspca_dev); + mutex_unlock(&gspca_dev->usb_lock); + } frame_free(gspca_dev); gspca_dev->capt_file = NULL; gspca_dev->memory = GSPCA_MEMORY_NO; -- cgit v0.10.2 From 8a5b2e909d56a1d5edec5e8f8848e03aafbc588e Mon Sep 17 00:00:00 2001 From: Hans de Goede Date: Wed, 3 Sep 2008 17:12:17 -0300 Subject: V4L/DVB (8825): gspca: More controls for pac73xx and new webcam 093a:2624. -Add usb id for 093a:2624 (pac7302) -Report some controls to userspace with 7302 only, as they are 7302 only -Add gain and exposure controls -Add autogain -Fix 7302 imaged being mirrored by default Signed-off-by: Hans de Goede Signed-off-by: Jean-Francois Moine Signed-off-by: Mauro Carvalho Chehab diff --git a/Documentation/video4linux/gspca.txt b/Documentation/video4linux/gspca.txt index 2dd2f77..c503467 100644 --- a/Documentation/video4linux/gspca.txt +++ b/Documentation/video4linux/gspca.txt @@ -188,6 +188,7 @@ pac7311 093a:2608 Trust WB-3300p pac7311 093a:260e Gigaware VGA PC Camera, Trust WB-3350p, SIGMA cam 2350 pac7311 093a:260f SnakeCam pac7311 093a:2621 PAC731x +pac7311 093a:2624 PAC7302 zc3xx 0ac8:0302 Z-star Vimicro zc0302 vc032x 0ac8:0321 Vimicro generic vc0321 vc032x 0ac8:0323 Vimicro Vc0323 diff --git a/drivers/media/video/gspca/pac207.c b/drivers/media/video/gspca/pac207.c index a15bcca..83b5f74 100644 --- a/drivers/media/video/gspca/pac207.c +++ b/drivers/media/video/gspca/pac207.c @@ -56,12 +56,6 @@ MODULE_LICENSE("GPL"); #define PAC207_GAIN_KNEE 20 #define PAC207_AUTOGAIN_DEADZONE 30 -/* We calculating the autogain at the end of the transfer of a frame, at this - moment a frame with the old settings is being transmitted, and a frame is - being captured with the old settings. So if we adjust the autogain we must - ignore atleast the 2 next frames for the new settings to come into effect - before doing any other adjustments */ -#define PAC207_AUTOGAIN_IGNORE_FRAMES 3 /* specific webcam descriptor */ struct sd { @@ -338,6 +332,9 @@ static void sd_stopN(struct gspca_dev *gspca_dev) pac207_write_reg(gspca_dev, 0x0f, 0x00); /* Power Control */ } +/* Include pac common sof detection functions */ +#include "pac_common.h" + static void pac207_do_auto_gain(struct gspca_dev *gspca_dev) { struct sd *sd = (struct sd *) gspca_dev; @@ -351,12 +348,9 @@ static void pac207_do_auto_gain(struct gspca_dev *gspca_dev) else if (gspca_auto_gain_n_exposure(gspca_dev, avg_lum, 100 + sd->brightness / 2, PAC207_AUTOGAIN_DEADZONE, PAC207_GAIN_KNEE, PAC207_EXPOSURE_KNEE)) - sd->autogain_ignore_frames = PAC207_AUTOGAIN_IGNORE_FRAMES; + sd->autogain_ignore_frames = PAC_AUTOGAIN_IGNORE_FRAMES; } -/* Include pac common sof detection functions */ -#include "pac_common.h" - static void sd_pkt_scan(struct gspca_dev *gspca_dev, struct gspca_frame *frame, __u8 *data, @@ -500,7 +494,7 @@ static int sd_setautogain(struct gspca_dev *gspca_dev, __s32 val) sd->gain = PAC207_GAIN_DEFAULT; if (gspca_dev->streaming) { sd->autogain_ignore_frames = - PAC207_AUTOGAIN_IGNORE_FRAMES; + PAC_AUTOGAIN_IGNORE_FRAMES; setexposure(gspca_dev); setgain(gspca_dev); } diff --git a/drivers/media/video/gspca/pac7311.c b/drivers/media/video/gspca/pac7311.c index e22ca61..14b9811 100644 --- a/drivers/media/video/gspca/pac7311.c +++ b/drivers/media/video/gspca/pac7311.c @@ -44,6 +44,9 @@ 0x10/- Master gain 0-31 -/0x10 Another gain 0-15, limited influence (1-2x gain I guess) 0x21 Bitfield: 0-1 unused, 2-3 vflip/hflip, 4-5 unknown, 6-7 unused + -/0x27 Seems to toggle various gains on / off, Setting bit 7 seems to + completely disable the analog amplification block. Set to 0x68 + for max gain, 0x14 for minimal gain. */ #define MODULE_NAME "pac7311" @@ -61,6 +64,8 @@ struct sd { unsigned char brightness; unsigned char contrast; unsigned char colors; + unsigned char gain; + unsigned char exposure; unsigned char autogain; __u8 hflip; __u8 vflip; @@ -88,8 +93,14 @@ static int sd_sethflip(struct gspca_dev *gspca_dev, __s32 val); static int sd_gethflip(struct gspca_dev *gspca_dev, __s32 *val); static int sd_setvflip(struct gspca_dev *gspca_dev, __s32 val); static int sd_getvflip(struct gspca_dev *gspca_dev, __s32 *val); +static int sd_setgain(struct gspca_dev *gspca_dev, __s32 val); +static int sd_getgain(struct gspca_dev *gspca_dev, __s32 *val); +static int sd_setexposure(struct gspca_dev *gspca_dev, __s32 val); +static int sd_getexposure(struct gspca_dev *gspca_dev, __s32 *val); static struct ctrl sd_ctrls[] = { +/* This control is pac7302 only */ +#define BRIGHTNESS_IDX 0 { { .id = V4L2_CID_BRIGHTNESS, @@ -105,6 +116,7 @@ static struct ctrl sd_ctrls[] = { .set = sd_setbrightness, .get = sd_getbrightness, }, +/* This control is for both the 7302 and the 7311 */ { { .id = V4L2_CID_CONTRAST, @@ -120,6 +132,8 @@ static struct ctrl sd_ctrls[] = { .set = sd_setcontrast, .get = sd_getcontrast, }, +/* This control is pac7302 only */ +#define SATURATION_IDX 2 { { .id = V4L2_CID_SATURATION, @@ -135,6 +149,39 @@ static struct ctrl sd_ctrls[] = { .set = sd_setcolors, .get = sd_getcolors, }, +/* All controls below are for both the 7302 and the 7311 */ + { + { + .id = V4L2_CID_GAIN, + .type = V4L2_CTRL_TYPE_INTEGER, + .name = "Gain", + .minimum = 0, +#define GAIN_MAX 255 + .maximum = GAIN_MAX, + .step = 1, +#define GAIN_DEF 127 +#define GAIN_KNEE 255 /* Gain seems to cause little noise on the pac73xx */ + .default_value = GAIN_DEF, + }, + .set = sd_setgain, + .get = sd_getgain, + }, + { + { + .id = V4L2_CID_EXPOSURE, + .type = V4L2_CTRL_TYPE_INTEGER, + .name = "Exposure", + .minimum = 0, +#define EXPOSURE_MAX 255 + .maximum = EXPOSURE_MAX, + .step = 1, +#define EXPOSURE_DEF 16 /* 32 ms / 30 fps */ +#define EXPOSURE_KNEE 50 /* 100 ms / 10 fps */ + .default_value = EXPOSURE_DEF, + }, + .set = sd_setexposure, + .get = sd_getexposure, + }, { { .id = V4L2_CID_AUTOGAIN, @@ -149,8 +196,6 @@ static struct ctrl sd_ctrls[] = { .set = sd_setautogain, .get = sd_getautogain, }, -/* next controls work with pac7302 only */ -#define HFLIP_IDX 4 { { .id = V4L2_CID_HFLIP, @@ -165,7 +210,6 @@ static struct ctrl sd_ctrls[] = { .set = sd_sethflip, .get = sd_gethflip, }, -#define VFLIP_IDX 5 { { .id = V4L2_CID_VFLIP, @@ -345,7 +389,7 @@ static const __u8 page4_7311[] = { 0x09, 0x00, 0xaa, 0xaa, 0x07, 0x00, 0x00, 0x62, 0x08, 0xaa, 0x07, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x03, 0xa0, 0x01, 0xf4, 0xaa, - 0xaa, 0x00, 0x08, 0xaa, 0x03, 0xaa, 0x00, 0x01, + 0xaa, 0x00, 0x08, 0xaa, 0x03, 0xaa, 0x00, 0x68, 0xca, 0x10, 0x06, 0x78, 0x00, 0x00, 0x00, 0x00, 0x23, 0x28, 0x04, 0x11, 0x00, 0x00 }; @@ -374,7 +418,7 @@ static void reg_w(struct gspca_dev *gspca_dev, usb_sndctrlpipe(gspca_dev->dev, 0), 0, /* request */ USB_DIR_OUT | USB_TYPE_VENDOR | USB_RECIP_DEVICE, - value, index, gspca_dev->usb_buf, 1, + 0, index, gspca_dev->usb_buf, 1, 500); } @@ -469,20 +513,22 @@ static int sd_config(struct gspca_dev *gspca_dev, cam->cam_mode = vga_mode; cam->nmodes = ARRAY_SIZE(vga_mode); - gspca_dev->ctrl_dis = (1 << HFLIP_IDX) - | (1 << VFLIP_IDX); + gspca_dev->ctrl_dis = (1 << BRIGHTNESS_IDX) + | (1 << SATURATION_IDX); } sd->brightness = BRIGHTNESS_DEF; sd->contrast = CONTRAST_DEF; sd->colors = COLOR_DEF; + sd->gain = GAIN_DEF; + sd->exposure = EXPOSURE_DEF; sd->autogain = AUTOGAIN_DEF; sd->hflip = HFLIP_DEF; sd->vflip = VFLIP_DEF; return 0; } -/* rev 12a only */ +/* This function is used by pac7302 only */ static void setbrightcont(struct gspca_dev *gspca_dev) { struct sd *sd = (struct sd *) gspca_dev; @@ -509,67 +555,95 @@ static void setbrightcont(struct gspca_dev *gspca_dev) reg_w(gspca_dev, 0xdc, 0x01); } -/* This function is used by pac7302 only */ -static void setbrightness(struct gspca_dev *gspca_dev) +/* This function is used by pac7311 only */ +static void setcontrast(struct gspca_dev *gspca_dev) { struct sd *sd = (struct sd *) gspca_dev; - int brightness; - - if (sd->sensor == SENSOR_PAC7302) { - setbrightcont(gspca_dev); - return; - } -/* HDG: this is not brightness but gain, I'll add gain and exposure controls - in a next patch */ - return; - brightness = BRIGHTNESS_MAX - sd->brightness; reg_w(gspca_dev, 0xff, 0x04); - reg_w(gspca_dev, 0x0e, 0x00); - reg_w(gspca_dev, 0x0f, brightness); + reg_w(gspca_dev, 0x10, sd->contrast >> 4); /* load registers to sensor (Bit 0, auto clear) */ reg_w(gspca_dev, 0x11, 0x01); - PDEBUG(D_CONF|D_STREAM, "brightness: %i", brightness); } -static void setcontrast(struct gspca_dev *gspca_dev) +/* This function is used by pac7302 only */ +static void setcolors(struct gspca_dev *gspca_dev) +{ + struct sd *sd = (struct sd *) gspca_dev; + int i, v; + static const int a[9] = + {217, -212, 0, -101, 170, -67, -38, -315, 355}; + static const int b[9] = + {19, 106, 0, 19, 106, 1, 19, 106, 1}; + + reg_w(gspca_dev, 0xff, 0x03); /* page 3 */ + reg_w(gspca_dev, 0x11, 0x01); + reg_w(gspca_dev, 0xff, 0x00); /* page 0 */ + reg_w(gspca_dev, 0xff, 0x00); /* page 0 */ + for (i = 0; i < 9; i++) { + v = a[i] * sd->colors / COLOR_MAX + b[i]; + reg_w(gspca_dev, 0x0f + 2 * i, (v >> 8) & 0x07); + reg_w(gspca_dev, 0x0f + 2 * i + 1, v); + } + reg_w(gspca_dev, 0xdc, 0x01); + PDEBUG(D_CONF|D_STREAM, "color: %i", sd->colors); +} + +static void setgain(struct gspca_dev *gspca_dev) { struct sd *sd = (struct sd *) gspca_dev; if (sd->sensor == SENSOR_PAC7302) { - setbrightcont(gspca_dev); - return; + reg_w(gspca_dev, 0xff, 0x03); /* page 3 */ + reg_w(gspca_dev, 0x10, sd->gain >> 3); + } else { + int gain = GAIN_MAX - sd->gain; + if (gain < 1) + gain = 1; + else if (gain > 245) + gain = 245; + reg_w(gspca_dev, 0xff, 0x04); /* page 4 */ + reg_w(gspca_dev, 0x0e, 0x00); + reg_w(gspca_dev, 0x0f, gain); } - reg_w(gspca_dev, 0xff, 0x04); - reg_w(gspca_dev, 0x10, sd->contrast >> 4); /* load registers to sensor (Bit 0, auto clear) */ reg_w(gspca_dev, 0x11, 0x01); } -/* This function is used by pac7302 only */ -static void setcolors(struct gspca_dev *gspca_dev) +static void setexposure(struct gspca_dev *gspca_dev) { struct sd *sd = (struct sd *) gspca_dev; + __u8 reg; + + /* register 2 of frame 3/4 contains the clock divider configuring the + no fps according to the formula: 60 / reg. sd->exposure is the + desired exposure time in ms. */ + reg = 120 * sd->exposure / 1000; + if (reg < 2) + reg = 2; + else if (reg > 63) + reg = 63; if (sd->sensor == SENSOR_PAC7302) { - int i, v; - static const int a[9] = - {217, -212, 0, -101, 170, -67, -38, -315, 355}; - static const int b[9] = - {19, 106, 0, 19, 106, 1, 19, 106, 1}; - - reg_w(gspca_dev, 0xff, 0x03); /* page 3 */ - reg_w(gspca_dev, 0x11, 0x01); - reg_w(gspca_dev, 0xff, 0x00); /* page 0 */ - reg_w(gspca_dev, 0xff, 0x00); /* page 0 */ - for (i = 0; i < 9; i++) { - v = a[i] * sd->colors / COLOR_MAX + b[i]; - reg_w(gspca_dev, 0x0f + 2 * i, (v >> 8) & 0x07); - reg_w(gspca_dev, 0x0f + 2 * i + 1, v); - } - reg_w(gspca_dev, 0xdc, 0x01); - PDEBUG(D_CONF|D_STREAM, "color: %i", sd->colors); + /* On the pac7302 reg2 MUST be a multiple of 3, so round it to + the nearest multiple of 3 */ + reg = ((reg + 1) / 3) * 3; + reg_w(gspca_dev, 0xff, 0x03); /* page 3 */ + reg_w(gspca_dev, 0x02, reg); + } else { + reg_w(gspca_dev, 0xff, 0x04); /* page 4 */ + reg_w(gspca_dev, 0x02, reg); + /* Page 1 register 8 must always be 0x08 except when not in + 640x480 mode and Page3/4 reg 2 <= 3 then it must be 9 */ + reg_w(gspca_dev, 0xff, 0x01); + if (gspca_dev->cam.cam_mode[(int)gspca_dev->curr_mode].priv && + reg <= 3) + reg_w(gspca_dev, 0x08, 0x09); + else + reg_w(gspca_dev, 0x08, 0x08); } + /* load registers to sensor (Bit 0, auto clear) */ + reg_w(gspca_dev, 0x11, 0x01); } static void sethvflip(struct gspca_dev *gspca_dev) @@ -579,14 +653,15 @@ static void sethvflip(struct gspca_dev *gspca_dev) if (sd->sensor == SENSOR_PAC7302) { reg_w(gspca_dev, 0xff, 0x03); /* page 3 */ - data = (sd->hflip ? 0x00 : 0x08) + data = (sd->hflip ? 0x08 : 0x00) | (sd->vflip ? 0x04 : 0x00); } else { - reg_w(gspca_dev, 0xff, 0x04); /* page 3 */ + reg_w(gspca_dev, 0xff, 0x04); /* page 4 */ data = (sd->hflip ? 0x04 : 0x00) | (sd->vflip ? 0x08 : 0x00); } reg_w(gspca_dev, 0x21, data); + /* load registers to sensor (Bit 0, auto clear) */ reg_w(gspca_dev, 0x11, 0x01); } @@ -602,61 +677,49 @@ static void sd_start(struct gspca_dev *gspca_dev) sd->sof_read = 0; - if (sd->sensor == SENSOR_PAC7302) + if (sd->sensor == SENSOR_PAC7302) { reg_w_var(gspca_dev, start_7302); - else + setbrightcont(gspca_dev); + setcolors(gspca_dev); + } else { reg_w_var(gspca_dev, start_7311); - - setcontrast(gspca_dev); - setbrightness(gspca_dev); - setcolors(gspca_dev); + setcontrast(gspca_dev); + } + setgain(gspca_dev); + setexposure(gspca_dev); + sethvflip(gspca_dev); /* set correct resolution */ switch (gspca_dev->cam.cam_mode[(int) gspca_dev->curr_mode].priv) { case 2: /* 160x120 pac7311 */ - reg_w(gspca_dev, 0xff, 0x04); - reg_w(gspca_dev, 0x02, 0x03); reg_w(gspca_dev, 0xff, 0x01); - reg_w(gspca_dev, 0x08, 0x09); reg_w(gspca_dev, 0x17, 0x20); - reg_w(gspca_dev, 0x1b, 0x00); reg_w(gspca_dev, 0x87, 0x10); break; case 1: /* 320x240 pac7311 */ - reg_w(gspca_dev, 0xff, 0x04); - reg_w(gspca_dev, 0x02, 0x03); reg_w(gspca_dev, 0xff, 0x01); - reg_w(gspca_dev, 0x08, 0x09); reg_w(gspca_dev, 0x17, 0x30); reg_w(gspca_dev, 0x87, 0x11); break; case 0: /* 640x480 */ if (sd->sensor == SENSOR_PAC7302) break; - reg_w(gspca_dev, 0xff, 0x04); - reg_w(gspca_dev, 0x02, 0x07); reg_w(gspca_dev, 0xff, 0x01); - reg_w(gspca_dev, 0x08, 0x08); reg_w(gspca_dev, 0x17, 0x00); reg_w(gspca_dev, 0x87, 0x12); break; } - /* start stream */ - reg_w(gspca_dev, 0xff, 0x01); - if (sd->sensor == SENSOR_PAC7302) { - sethvflip(gspca_dev); - reg_w(gspca_dev, 0x78, 0x01); - reg_w(gspca_dev, 0xff, 0x01); - reg_w(gspca_dev, 0x78, 0x01); - } else { - reg_w(gspca_dev, 0x78, 0x44); - reg_w(gspca_dev, 0x78, 0x45); - } - sd->sof_read = 0; sd->autogain_ignore_frames = 0; atomic_set(&sd->avg_lum, -1); + + /* start stream */ + reg_w(gspca_dev, 0xff, 0x01); + if (sd->sensor == SENSOR_PAC7302) + reg_w(gspca_dev, 0x78, 0x01); + else + reg_w(gspca_dev, 0x78, 0x05); } static void sd_stopN(struct gspca_dev *gspca_dev) @@ -691,8 +754,28 @@ static void sd_stop0(struct gspca_dev *gspca_dev) } } +/* Include pac common sof detection functions */ +#include "pac_common.h" + static void do_autogain(struct gspca_dev *gspca_dev) { + struct sd *sd = (struct sd *) gspca_dev; + int avg_lum = atomic_read(&sd->avg_lum); + int desired_lum; + + if (avg_lum == -1) + return; + + if (sd->sensor == SENSOR_PAC7302) + desired_lum = 70 + sd->brightness * 2; + else + desired_lum = 200; + + if (sd->autogain_ignore_frames > 0) + sd->autogain_ignore_frames--; + else if (gspca_auto_gain_n_exposure(gspca_dev, avg_lum, desired_lum, + 10, GAIN_KNEE, EXPOSURE_KNEE)) + sd->autogain_ignore_frames = PAC_AUTOGAIN_IGNORE_FRAMES; } static const unsigned char pac7311_jpeg_header1[] = { @@ -704,9 +787,6 @@ static const unsigned char pac7311_jpeg_header2[] = { 0x00, 0x0c, 0x03, 0x01, 0x00, 0x02, 0x11, 0x03, 0x11, 0x00, 0x3f, 0x00 }; -/* Include pac common sof detection functions */ -#include "pac_common.h" - /* this function is run at interrupt level */ static void sd_pkt_scan(struct gspca_dev *gspca_dev, struct gspca_frame *frame, /* target */ @@ -790,7 +870,7 @@ static int sd_setbrightness(struct gspca_dev *gspca_dev, __s32 val) sd->brightness = val; if (gspca_dev->streaming) - setbrightness(gspca_dev); + setbrightcont(gspca_dev); return 0; } @@ -807,8 +887,12 @@ static int sd_setcontrast(struct gspca_dev *gspca_dev, __s32 val) struct sd *sd = (struct sd *) gspca_dev; sd->contrast = val; - if (gspca_dev->streaming) - setcontrast(gspca_dev); + if (gspca_dev->streaming) { + if (sd->sensor == SENSOR_PAC7302) + setbrightcont(gspca_dev); + else + setcontrast(gspca_dev); + } return 0; } @@ -838,11 +922,61 @@ static int sd_getcolors(struct gspca_dev *gspca_dev, __s32 *val) return 0; } +static int sd_setgain(struct gspca_dev *gspca_dev, __s32 val) +{ + struct sd *sd = (struct sd *) gspca_dev; + + sd->gain = val; + if (gspca_dev->streaming) + setgain(gspca_dev); + return 0; +} + +static int sd_getgain(struct gspca_dev *gspca_dev, __s32 *val) +{ + struct sd *sd = (struct sd *) gspca_dev; + + *val = sd->gain; + return 0; +} + +static int sd_setexposure(struct gspca_dev *gspca_dev, __s32 val) +{ + struct sd *sd = (struct sd *) gspca_dev; + + sd->exposure = val; + if (gspca_dev->streaming) + setexposure(gspca_dev); + return 0; +} + +static int sd_getexposure(struct gspca_dev *gspca_dev, __s32 *val) +{ + struct sd *sd = (struct sd *) gspca_dev; + + *val = sd->exposure; + return 0; +} + static int sd_setautogain(struct gspca_dev *gspca_dev, __s32 val) { struct sd *sd = (struct sd *) gspca_dev; sd->autogain = val; + /* when switching to autogain set defaults to make sure + we are on a valid point of the autogain gain / + exposure knee graph, and give this change time to + take effect before doing autogain. */ + if (sd->autogain) { + sd->exposure = EXPOSURE_DEF; + sd->gain = GAIN_DEF; + if (gspca_dev->streaming) { + sd->autogain_ignore_frames = + PAC_AUTOGAIN_IGNORE_FRAMES; + setexposure(gspca_dev); + setgain(gspca_dev); + } + } return 0; } @@ -914,6 +1048,7 @@ static __devinitdata struct usb_device_id device_table[] = { {USB_DEVICE(0x093a, 0x260e), .driver_info = SENSOR_PAC7311}, {USB_DEVICE(0x093a, 0x260f), .driver_info = SENSOR_PAC7311}, {USB_DEVICE(0x093a, 0x2621), .driver_info = SENSOR_PAC7302}, + {USB_DEVICE(0x093a, 0x2624), .driver_info = SENSOR_PAC7302}, {} }; MODULE_DEVICE_TABLE(usb, device_table); diff --git a/drivers/media/video/gspca/pac_common.h b/drivers/media/video/gspca/pac_common.h index a19b5d4..34d4b14 100644 --- a/drivers/media/video/gspca/pac_common.h +++ b/drivers/media/video/gspca/pac_common.h @@ -23,6 +23,13 @@ * */ +/* We calculate the autogain at the end of the transfer of a frame, at this + moment a frame with the old settings is being transmitted, and a frame is + being captured with the old settings. So if we adjust the autogain we must + ignore atleast the 2 next frames for the new settings to come into effect + before doing any other adjustments */ +#define PAC_AUTOGAIN_IGNORE_FRAMES 3 + static const unsigned char pac_sof_marker[5] = { 0xff, 0xff, 0x00, 0xff, 0x96 }; @@ -37,7 +44,7 @@ static unsigned char *pac_find_sof(struct gspca_dev *gspca_dev, if (m[i] == pac_sof_marker[sd->sof_read]) { sd->sof_read++; if (sd->sof_read == sizeof(pac_sof_marker)) { - PDEBUG(D_STREAM, + PDEBUG(D_FRAM, "SOF found, bytes to analyze: %u." " Frame starts at byte #%u", len, i + 1); -- cgit v0.10.2 From 086272555d1b7936512de1e6d9efacdf87169cb0 Mon Sep 17 00:00:00 2001 From: Jean-Francois Moine Date: Wed, 3 Sep 2008 17:12:17 -0300 Subject: V4L/DVB (8826): gspca: Webcam Labtec 2200 (093a:2626) added in pac7311. Signed-off-by: Jean-Francois Moine Signed-off-by: Mauro Carvalho Chehab diff --git a/Documentation/video4linux/gspca.txt b/Documentation/video4linux/gspca.txt index c503467..0f03900 100644 --- a/Documentation/video4linux/gspca.txt +++ b/Documentation/video4linux/gspca.txt @@ -189,6 +189,7 @@ pac7311 093a:260e Gigaware VGA PC Camera, Trust WB-3350p, SIGMA cam 2350 pac7311 093a:260f SnakeCam pac7311 093a:2621 PAC731x pac7311 093a:2624 PAC7302 +pac7311 093a:2626 Labtec 2200 zc3xx 0ac8:0302 Z-star Vimicro zc0302 vc032x 0ac8:0321 Vimicro generic vc0321 vc032x 0ac8:0323 Vimicro Vc0323 diff --git a/drivers/media/video/gspca/pac7311.c b/drivers/media/video/gspca/pac7311.c index 14b9811..35244cf 100644 --- a/drivers/media/video/gspca/pac7311.c +++ b/drivers/media/video/gspca/pac7311.c @@ -1049,6 +1049,7 @@ static __devinitdata struct usb_device_id device_table[] = { {USB_DEVICE(0x093a, 0x260f), .driver_info = SENSOR_PAC7311}, {USB_DEVICE(0x093a, 0x2621), .driver_info = SENSOR_PAC7302}, {USB_DEVICE(0x093a, 0x2624), .driver_info = SENSOR_PAC7302}, + {USB_DEVICE(0x093a, 0x2626), .driver_info = SENSOR_PAC7302}, {} }; MODULE_DEVICE_TABLE(usb, device_table); -- cgit v0.10.2 From 038ec7c772cb093411b163c22f389787722cfd8e Mon Sep 17 00:00:00 2001 From: Hans de Goede Date: Wed, 3 Sep 2008 17:12:18 -0300 Subject: V4L/DVB (8827): gspca: Stop pac7302 autogain oscillation. Signed-off-by: Hans de Goede Signed-off-by: Jean-Francois Moine Signed-off-by: Mauro Carvalho Chehab diff --git a/drivers/media/video/gspca/pac7311.c b/drivers/media/video/gspca/pac7311.c index 35244cf..723219d 100644 --- a/drivers/media/video/gspca/pac7311.c +++ b/drivers/media/video/gspca/pac7311.c @@ -39,7 +39,7 @@ Address Description 0x02 Clock divider 2-63, fps =~ 60 / val. Must be a multiple of 3 on - the 7302, so one of 3, 6, 9, ... + the 7302, so one of 3, 6, 9, ..., except when between 6 and 12? -/0x0f Master gain 1-245, low value = high gain 0x10/- Master gain 0-31 -/0x10 Another gain 0-15, limited influence (1-2x gain I guess) @@ -626,8 +626,9 @@ static void setexposure(struct gspca_dev *gspca_dev) if (sd->sensor == SENSOR_PAC7302) { /* On the pac7302 reg2 MUST be a multiple of 3, so round it to - the nearest multiple of 3 */ - reg = ((reg + 1) / 3) * 3; + the nearest multiple of 3, except when between 6 and 12? */ + if (reg < 6 || reg > 12) + reg = ((reg + 1) / 3) * 3; reg_w(gspca_dev, 0xff, 0x03); /* page 3 */ reg_w(gspca_dev, 0x02, reg); } else { @@ -761,20 +762,32 @@ static void do_autogain(struct gspca_dev *gspca_dev) { struct sd *sd = (struct sd *) gspca_dev; int avg_lum = atomic_read(&sd->avg_lum); - int desired_lum; + int desired_lum, deadzone; if (avg_lum == -1) return; - if (sd->sensor == SENSOR_PAC7302) - desired_lum = 70 + sd->brightness * 2; - else + if (sd->sensor == SENSOR_PAC7302) { + desired_lum = 270 + sd->brightness * 4; + /* Hack hack, with the 7202 the first exposure step is + pretty large, so if we're about to make the first + exposure increase make the deadzone large to avoid + oscilating */ + if (desired_lum > avg_lum && sd->gain == GAIN_DEF && + sd->exposure > EXPOSURE_DEF && + sd->exposure < 42) + deadzone = 90; + else + deadzone = 30; + } else { desired_lum = 200; + deadzone = 20; + } if (sd->autogain_ignore_frames > 0) sd->autogain_ignore_frames--; else if (gspca_auto_gain_n_exposure(gspca_dev, avg_lum, desired_lum, - 10, GAIN_KNEE, EXPOSURE_KNEE)) + deadzone, GAIN_KNEE, EXPOSURE_KNEE)) sd->autogain_ignore_frames = PAC_AUTOGAIN_IGNORE_FRAMES; } @@ -802,7 +815,11 @@ static void sd_pkt_scan(struct gspca_dev *gspca_dev, int n, lum_offset, footer_length; if (sd->sensor == SENSOR_PAC7302) { - lum_offset = 34 + sizeof pac_sof_marker; + /* 6 bytes after the FF D9 EOF marker a number of lumination + bytes are send corresponding to different parts of the + image, the 14th and 15th byte after the EOF seem to + correspond to the center of the image */ + lum_offset = 61 + sizeof pac_sof_marker; footer_length = 74; } else { lum_offset = 24 + sizeof pac_sof_marker; @@ -829,18 +846,11 @@ static void sd_pkt_scan(struct gspca_dev *gspca_dev, /* Get average lumination */ if (gspca_dev->last_packet_type == LAST_PACKET && - n >= lum_offset) { - if (sd->sensor == SENSOR_PAC7302) - atomic_set(&sd->avg_lum, - (data[-lum_offset] << 8) | - data[-lum_offset + 1]); - else - atomic_set(&sd->avg_lum, - data[-lum_offset] + + n >= lum_offset) + atomic_set(&sd->avg_lum, data[-lum_offset] + data[-lum_offset + 1]); - } else { + else atomic_set(&sd->avg_lum, -1); - } /* Start the new frame with the jpeg header */ gspca_frame_add(gspca_dev, FIRST_PACKET, frame, -- cgit v0.10.2 From 91de65ac00f976c972940bedd9dbfe38bb8bfec3 Mon Sep 17 00:00:00 2001 From: Jean-Francois Moine Date: Wed, 3 Sep 2008 17:12:18 -0300 Subject: V4L/DVB (8828): gspca: Set the clock at the end of initialization in sonixj. Signed-off-by: Jean-Francois Moine Signed-off-by: Mauro Carvalho Chehab diff --git a/drivers/media/video/gspca/sonixj.c b/drivers/media/video/gspca/sonixj.c index 5380b43..feb17db 100644 --- a/drivers/media/video/gspca/sonixj.c +++ b/drivers/media/video/gspca/sonixj.c @@ -444,7 +444,7 @@ static const __u8 ov7630_sensor_init[][8] = { {0xa1, 0x21, 0x2b, 0x34, 0x00, 0x00, 0x00, 0x10}, /* */ {0xa1, 0x21, 0x10, 0x83, 0x00, 0x00, 0x00, 0x10}, - {0xb1, 0x21, 0x01, 0x88, 0x70, 0x00, 0x00, 0x10}, +/* {0xb1, 0x21, 0x01, 0x88, 0x70, 0x00, 0x00, 0x10}, */ {} }; static const __u8 ov7660_sensor_init[][8] = { @@ -811,6 +811,13 @@ static int configure_gpio(struct gspca_dev *gspca_dev, reg_w1(gspca_dev, 0x17, 0xae); reg_w1(gspca_dev, 0x01, 0x42); break; +/*jfm: from win trace */ + case SENSOR_OV7660: + reg_w1(gspca_dev, 0x01, 0x61); + reg_w1(gspca_dev, 0x17, 0x20); + reg_w1(gspca_dev, 0x01, 0x60); + reg_w1(gspca_dev, 0x01, 0x40); + break; default: reg_w1(gspca_dev, 0x01, 0x43); reg_w1(gspca_dev, 0x17, 0x61); @@ -1076,7 +1083,7 @@ static void setbrightcont(struct gspca_dev *gspca_dev) { struct sd *sd = (struct sd *) gspca_dev; unsigned val; - __u8 reg84_full[13]; + __u8 reg84_full[0x15]; memset(reg84_full, 0, sizeof reg84_full); val = sd->contrast * 0x20 / CONTRAST_MAX + 0x10; /* 10..30 */ @@ -1088,7 +1095,7 @@ static void setbrightcont(struct gspca_dev *gspca_dev) / BRIGHTNESS_MAX; else val = 0; - reg84_full[10] = val; /* 00..1f */ + reg84_full[0x12] = val; /* 00..1f */ reg_w(gspca_dev, 0x84, reg84_full, sizeof reg84_full); } @@ -1184,7 +1191,6 @@ static void sd_start(struct gspca_dev *gspca_dev) sn9c1xx = sn_tb[(int) sd->sensor]; configure_gpio(gspca_dev, sn9c1xx); -/* reg_w1(gspca_dev, 0x01, 0x44); jfm from win trace*/ reg_w1(gspca_dev, 0x15, sn9c1xx[0x15]); reg_w1(gspca_dev, 0x16, sn9c1xx[0x16]); reg_w1(gspca_dev, 0x12, sn9c1xx[0x12]); @@ -1300,7 +1306,6 @@ static void sd_start(struct gspca_dev *gspca_dev) reg_w1(gspca_dev, 0x18, reg18); reg_w1(gspca_dev, 0x17, reg17); - reg_w1(gspca_dev, 0x01, reg1); switch (sd->sensor) { case SENSOR_HV7131R: case SENSOR_MI0360: @@ -1314,6 +1319,7 @@ static void sd_start(struct gspca_dev *gspca_dev) break; } setautogain(gspca_dev); + reg_w1(gspca_dev, 0x01, reg1); } static void sd_stopN(struct gspca_dev *gspca_dev) -- cgit v0.10.2 From 8295d99ee5340f1e62b53c8adc979e0789299445 Mon Sep 17 00:00:00 2001 From: Jean-Francois Moine Date: Wed, 3 Sep 2008 17:12:19 -0300 Subject: V4L/DVB (8829): gspca: Have a clean kmalloc-ated buffer for USB exchanges. The USB buffer may be used for DMA and there may be a caching problem if the buffer is part of the device structure. Thanks to Alan Stern. Signed-off-by: Jean-Francois Moine Signed-off-by: Mauro Carvalho Chehab diff --git a/drivers/media/video/gspca/conex.c b/drivers/media/video/gspca/conex.c index 3db5c1e..8c91ffd 100644 --- a/drivers/media/video/gspca/conex.c +++ b/drivers/media/video/gspca/conex.c @@ -124,7 +124,7 @@ static void reg_r(struct gspca_dev *gspca_dev, struct usb_device *dev = gspca_dev->dev; #ifdef GSPCA_DEBUG - if (len > sizeof gspca_dev->usb_buf) { + if (len > USB_BUF_SZ) { err("reg_r: buffer overflow"); return; } @@ -164,7 +164,7 @@ static void reg_w(struct gspca_dev *gspca_dev, struct usb_device *dev = gspca_dev->dev; #ifdef GSPCA_DEBUG - if (len > sizeof gspca_dev->usb_buf) { + if (len > USB_BUF_SZ) { err("reg_w: buffer overflow"); return; } diff --git a/drivers/media/video/gspca/etoms.c b/drivers/media/video/gspca/etoms.c index c03b1f4..9eb6adb 100644 --- a/drivers/media/video/gspca/etoms.c +++ b/drivers/media/video/gspca/etoms.c @@ -235,7 +235,7 @@ static void reg_r(struct gspca_dev *gspca_dev, struct usb_device *dev = gspca_dev->dev; #ifdef GSPCA_DEBUG - if (len > sizeof gspca_dev->usb_buf) { + if (len > USB_BUF_SZ) { err("reg_r: buffer overflow"); return; } @@ -273,7 +273,7 @@ static void reg_w(struct gspca_dev *gspca_dev, struct usb_device *dev = gspca_dev->dev; #ifdef GSPCA_DEBUG - if (len > sizeof gspca_dev->usb_buf) { + if (len > USB_BUF_SZ) { err("reg_w: buffer overflow"); return; } diff --git a/drivers/media/video/gspca/gspca.c b/drivers/media/video/gspca/gspca.c index 42b0b83..7be6928 100644 --- a/drivers/media/video/gspca/gspca.c +++ b/drivers/media/video/gspca/gspca.c @@ -1731,6 +1731,12 @@ int gspca_dev_probe(struct usb_interface *intf, err("couldn't kzalloc gspca struct"); return -EIO; } + gspca_dev->usb_buf = kmalloc(USB_BUF_SZ, GFP_KERNEL); + if (!gspca_dev->usb_buf) { + err("out of memory"); + ret = -EIO; + goto out; + } gspca_dev->dev = dev; gspca_dev->iface = interface->bInterfaceNumber; gspca_dev->nbalt = intf->num_altsetting; @@ -1774,6 +1780,7 @@ int gspca_dev_probe(struct usb_interface *intf, PDEBUG(D_PROBE, "probe ok"); return 0; out: + kfree(gspca_dev->usb_buf); kfree(gspca_dev); return ret; } @@ -1806,6 +1813,7 @@ void gspca_disconnect(struct usb_interface *intf) /* We don't want people trying to open up the device */ video_unregister_device(&gspca_dev->vdev); /* Free the memory */ + kfree(gspca_dev->usb_buf); kfree(gspca_dev); PDEBUG(D_PROBE, "disconnect complete"); } diff --git a/drivers/media/video/gspca/gspca.h b/drivers/media/video/gspca/gspca.h index 7c2f44b2..c17625c 100644 --- a/drivers/media/video/gspca/gspca.h +++ b/drivers/media/video/gspca/gspca.h @@ -127,7 +127,8 @@ struct gspca_dev { const struct sd_desc *sd_desc; /* subdriver description */ unsigned ctrl_dis; /* disabled controls (bit map) */ - __u8 usb_buf[8]; /* buffer for USB exchanges */ +#define USB_BUF_SZ 64 + __u8 *usb_buf; /* buffer for USB exchanges */ struct urb *urb[MAX_NURBS]; __u8 *frbuf; /* buffer for nframes */ diff --git a/drivers/media/video/gspca/mars.c b/drivers/media/video/gspca/mars.c index 2814759..4d5db47 100644 --- a/drivers/media/video/gspca/mars.c +++ b/drivers/media/video/gspca/mars.c @@ -100,22 +100,6 @@ static int reg_w(struct gspca_dev *gspca_dev, return rc; } -static int reg_w_buf(struct gspca_dev *gspca_dev, - __u16 index, __u8 *buf, int len) -{ - int rc; - - rc = usb_control_msg(gspca_dev->dev, - usb_sndbulkpipe(gspca_dev->dev, 4), - 0x12, - 0xc8, /* ?? */ - 0, /* value */ - index, buf, len, 500); - if (rc < 0) - PDEBUG(D_ERR, "reg write [%02x] error %d", index, rc); - return rc; -} - static void bulk_w(struct gspca_dev *gspca_dev, __u16 *pch, __u16 Address) @@ -175,7 +159,6 @@ static void sd_start(struct gspca_dev *gspca_dev) /* Initialize the MR97113 chip register */ - data = kmalloc(16, GFP_KERNEL); data[0] = 0x00; /* address */ data[1] = 0x0c | 0x01; /* reg 0 */ data[2] = 0x01; /* reg 1 */ @@ -195,12 +178,10 @@ static void sd_start(struct gspca_dev *gspca_dev) data[10] = 0x5d; /* reg 9, I2C device address * [for PAS5101 (0x40)] [for MI (0x5d)] */ - err_code = reg_w_buf(gspca_dev, data[0], data, 11); - kfree(data); + err_code = reg_w(gspca_dev, data[0], 11); if (err_code < 0) return; - data = gspca_dev->usb_buf; data[0] = 0x23; /* address */ data[1] = 0x09; /* reg 35, append frame header */ diff --git a/drivers/media/video/gspca/sonixb.c b/drivers/media/video/gspca/sonixb.c index 044a9ec..162beb3 100644 --- a/drivers/media/video/gspca/sonixb.c +++ b/drivers/media/video/gspca/sonixb.c @@ -410,7 +410,7 @@ static void reg_w(struct gspca_dev *gspca_dev, int len) { #ifdef GSPCA_DEBUG - if (len > sizeof gspca_dev->usb_buf) { + if (len > USB_BUF_SZ) { PDEBUG(D_ERR|D_PACK, "reg_w: buffer overflow"); return; } @@ -426,26 +426,6 @@ static void reg_w(struct gspca_dev *gspca_dev, 500); } -static void reg_w_big(struct gspca_dev *gspca_dev, - __u16 value, - const __u8 *buffer, - int len) -{ - __u8 *tmpbuf; - - tmpbuf = kmalloc(len, GFP_KERNEL); - memcpy(tmpbuf, buffer, len); - usb_control_msg(gspca_dev->dev, - usb_sndctrlpipe(gspca_dev->dev, 0), - 0x08, /* request */ - USB_DIR_OUT | USB_TYPE_VENDOR | USB_RECIP_INTERFACE, - value, - 0, /* index */ - tmpbuf, len, - 500); - kfree(tmpbuf); -} - static int i2c_w(struct gspca_dev *gspca_dev, const __u8 *buffer) { int retry = 60; @@ -886,7 +866,7 @@ static void sd_start(struct gspca_dev *gspca_dev) /* reg 0x17 SensorClk enable inv Clk 0x60 */ reg_w(gspca_dev, 0x17, &sn9c10x[0x17 - 1], 1); /* Set the registers from the template */ - reg_w_big(gspca_dev, 0x01, sn9c10x, l); + reg_w(gspca_dev, 0x01, sn9c10x, l); switch (sd->sensor) { case SENSOR_HV7131R: i2c_w_vector(gspca_dev, hv7131_sensor_init, diff --git a/drivers/media/video/gspca/sonixj.c b/drivers/media/video/gspca/sonixj.c index feb17db..5697959 100644 --- a/drivers/media/video/gspca/sonixj.c +++ b/drivers/media/video/gspca/sonixj.c @@ -613,10 +613,16 @@ static const __u8 qtable4[] = { 0x29, 0x29, 0x29, 0x29 }; -/* read bytes (len < sizeof gspca_dev->usb_buf) to gspca_dev->usb_buf */ +/* read bytes to gspca_dev->usb_buf */ static void reg_r(struct gspca_dev *gspca_dev, __u16 value, int len) { +#ifdef GSPCA_DEBUG + if (len > USB_BUF_SZ) { + err("reg_r: buffer overflow"); + return; + } +#endif usb_control_msg(gspca_dev->dev, usb_rcvctrlpipe(gspca_dev->dev, 0), 0, @@ -649,29 +655,20 @@ static void reg_w(struct gspca_dev *gspca_dev, { PDEBUG(D_USBO, "reg_w [%02x] = %02x %02x ..", value, buffer[0], buffer[1]); - if (len <= sizeof gspca_dev->usb_buf) { - memcpy(gspca_dev->usb_buf, buffer, len); - usb_control_msg(gspca_dev->dev, - usb_sndctrlpipe(gspca_dev->dev, 0), - 0x08, - USB_DIR_OUT | USB_TYPE_VENDOR | USB_RECIP_INTERFACE, - value, 0, - gspca_dev->usb_buf, len, - 500); - } else { - __u8 *tmpbuf; - - tmpbuf = kmalloc(len, GFP_KERNEL); - memcpy(tmpbuf, buffer, len); - usb_control_msg(gspca_dev->dev, - usb_sndctrlpipe(gspca_dev->dev, 0), - 0x08, - USB_DIR_OUT | USB_TYPE_VENDOR | USB_RECIP_INTERFACE, - value, 0, - tmpbuf, len, - 500); - kfree(tmpbuf); +#ifdef GSPCA_DEBUG + if (len > USB_BUF_SZ) { + err("reg_w: buffer overflow"); + return; } +#endif + memcpy(gspca_dev->usb_buf, buffer, len); + usb_control_msg(gspca_dev->dev, + usb_sndctrlpipe(gspca_dev->dev, 0), + 0x08, + USB_DIR_OUT | USB_TYPE_VENDOR | USB_RECIP_INTERFACE, + value, 0, + gspca_dev->usb_buf, len, + 500); } /* I2C write 1 byte */ diff --git a/drivers/media/video/gspca/sunplus.c b/drivers/media/video/gspca/sunplus.c index bddf733..1cfcc6c 100644 --- a/drivers/media/video/gspca/sunplus.c +++ b/drivers/media/video/gspca/sunplus.c @@ -449,31 +449,47 @@ static const __u8 qtable_spca504_default[2][64] = { 0x1e, 0x1e, 0x1e, 0x1e, 0x1e, 0x1e, 0x1e, 0x1e} }; -static void reg_r(struct usb_device *dev, - __u16 req, - __u16 index, - __u8 *buffer, __u16 length) +/* read bytes to gspca_dev->usb_buf */ +static void reg_r(struct gspca_dev *gspca_dev, + __u16 req, + __u16 index, + __u16 len) { - usb_control_msg(dev, - usb_rcvctrlpipe(dev, 0), +#ifdef GSPCA_DEBUG + if (len > USB_BUF_SZ) { + err("reg_r: buffer overflow"); + return; + } +#endif + usb_control_msg(gspca_dev->dev, + usb_rcvctrlpipe(gspca_dev->dev, 0), req, USB_DIR_IN | USB_TYPE_VENDOR | USB_RECIP_DEVICE, 0, /* value */ - index, buffer, length, + index, + len ? gspca_dev->usb_buf : NULL, len, 500); } -static void reg_w(struct usb_device *dev, - __u16 req, - __u16 value, - __u16 index, - __u8 *buffer, __u16 length) +/* write bytes from gspca_dev->usb_buf */ +static void reg_w(struct gspca_dev *gspca_dev, + __u16 req, + __u16 value, + __u16 index, + __u16 len) { - usb_control_msg(dev, - usb_sndctrlpipe(dev, 0), +#ifdef GSPCA_DEBUG + if (len > USB_BUF_SZ) { + err("reg_w: buffer overflow"); + return; + } +#endif + usb_control_msg(gspca_dev->dev, + usb_sndctrlpipe(gspca_dev->dev, 0), req, USB_DIR_OUT | USB_TYPE_VENDOR | USB_RECIP_DEVICE, - value, index, buffer, length, + value, index, + len ? gspca_dev->usb_buf : NULL, len, 500); } @@ -634,7 +650,7 @@ static int spca504B_PollingDataReady(struct gspca_dev *gspca_dev) int count = 10; while (--count > 0) { - reg_r(gspca_dev->dev, 0x21, 0, gspca_dev->usb_buf, 1); + reg_r(gspca_dev, 0x21, 0, 1); if ((gspca_dev->usb_buf[0] & 0x01) == 0) break; msleep(10); @@ -644,15 +660,14 @@ static int spca504B_PollingDataReady(struct gspca_dev *gspca_dev) static void spca504B_WaitCmdStatus(struct gspca_dev *gspca_dev) { - struct usb_device *dev = gspca_dev->dev; int count = 50; while (--count > 0) { - reg_r(dev, 0x21, 1, gspca_dev->usb_buf, 1); + reg_r(gspca_dev, 0x21, 1, 1); if (gspca_dev->usb_buf[0] != 0) { gspca_dev->usb_buf[0] = 0; - reg_w(dev, 0x21, 0, 1, gspca_dev->usb_buf, 1); - reg_r(dev, 0x21, 1, gspca_dev->usb_buf, 1); + reg_w(gspca_dev, 0x21, 0, 1, 1); + reg_r(gspca_dev, 0x21, 1, 1); spca504B_PollingDataReady(gspca_dev); break; } @@ -662,16 +677,14 @@ static void spca504B_WaitCmdStatus(struct gspca_dev *gspca_dev) static void spca50x_GetFirmware(struct gspca_dev *gspca_dev) { - struct usb_device *dev = gspca_dev->dev; __u8 *data; - data = kmalloc(64, GFP_KERNEL); - reg_r(dev, 0x20, 0, data, 5); + data = gspca_dev->usb_buf; + reg_r(gspca_dev, 0x20, 0, 5); PDEBUG(D_STREAM, "FirmWare : %d %d %d %d %d ", data[0], data[1], data[2], data[3], data[4]); - reg_r(dev, 0x23, 0, data, 64); - reg_r(dev, 0x23, 1, data, 64); - kfree(data); + reg_r(gspca_dev, 0x23, 0, 64); + reg_r(gspca_dev, 0x23, 1, 64); } static void spca504B_SetSizeType(struct gspca_dev *gspca_dev) @@ -686,21 +699,21 @@ static void spca504B_SetSizeType(struct gspca_dev *gspca_dev) Type = 0; switch (sd->bridge) { case BRIDGE_SPCA533: - reg_w(dev, 0x31, 0, 0, NULL, 0); + reg_w(gspca_dev, 0x31, 0, 0, 0); spca504B_WaitCmdStatus(gspca_dev); rc = spca504B_PollingDataReady(gspca_dev); spca50x_GetFirmware(gspca_dev); gspca_dev->usb_buf[0] = 2; /* type */ - reg_w(dev, 0x24, 0, 8, gspca_dev->usb_buf, 1); - reg_r(dev, 0x24, 8, gspca_dev->usb_buf, 1); + reg_w(gspca_dev, 0x24, 0, 8, 1); + reg_r(gspca_dev, 0x24, 8, 1); gspca_dev->usb_buf[0] = Size; - reg_w(dev, 0x25, 0, 4, gspca_dev->usb_buf, 1); - reg_r(dev, 0x25, 4, gspca_dev->usb_buf, 1); /* size */ + reg_w(gspca_dev, 0x25, 0, 4, 1); + reg_r(gspca_dev, 0x25, 4, 1); /* size */ rc = spca504B_PollingDataReady(gspca_dev); /* Init the cam width height with some values get on init ? */ - reg_w(dev, 0x31, 0, 4, NULL, 0); + reg_w(gspca_dev, 0x31, 0, 4, 0); spca504B_WaitCmdStatus(gspca_dev); rc = spca504B_PollingDataReady(gspca_dev); break; @@ -708,12 +721,12 @@ static void spca504B_SetSizeType(struct gspca_dev *gspca_dev) /* case BRIDGE_SPCA504B: */ /* case BRIDGE_SPCA536: */ gspca_dev->usb_buf[0] = Size; - reg_w(dev, 0x25, 0, 4, gspca_dev->usb_buf, 1); - reg_r(dev, 0x25, 4, gspca_dev->usb_buf, 1); /* size */ + reg_w(gspca_dev, 0x25, 0, 4, 1); + reg_r(gspca_dev, 0x25, 4, 1); /* size */ Type = 6; gspca_dev->usb_buf[0] = Type; - reg_w(dev, 0x27, 0, 0, gspca_dev->usb_buf, 1); - reg_r(dev, 0x27, 0, gspca_dev->usb_buf, 1); /* type */ + reg_w(gspca_dev, 0x27, 0, 0, 1); + reg_r(gspca_dev, 0x27, 0, 1); /* type */ rc = spca504B_PollingDataReady(gspca_dev); break; case BRIDGE_SPCA504: @@ -752,18 +765,15 @@ static void spca504_wait_status(struct gspca_dev *gspca_dev) static void spca504B_setQtable(struct gspca_dev *gspca_dev) { - struct usb_device *dev = gspca_dev->dev; - gspca_dev->usb_buf[0] = 3; - reg_w(dev, 0x26, 0, 0, gspca_dev->usb_buf, 1); - reg_r(dev, 0x26, 0, gspca_dev->usb_buf, 1); + reg_w(gspca_dev, 0x26, 0, 0, 1); + reg_r(gspca_dev, 0x26, 0, 1); spca504B_PollingDataReady(gspca_dev); } static void sp5xx_initContBrigHueRegisters(struct gspca_dev *gspca_dev) { struct sd *sd = (struct sd *) gspca_dev; - struct usb_device *dev = gspca_dev->dev; int pollreg = 1; switch (sd->bridge) { @@ -774,20 +784,20 @@ static void sp5xx_initContBrigHueRegisters(struct gspca_dev *gspca_dev) default: /* case BRIDGE_SPCA533: */ /* case BRIDGE_SPCA504B: */ - reg_w(dev, 0, 0, 0x21a7, NULL, 0); /* brightness */ - reg_w(dev, 0, 0x20, 0x21a8, NULL, 0); /* contrast */ - reg_w(dev, 0, 0, 0x21ad, NULL, 0); /* hue */ - reg_w(dev, 0, 1, 0x21ac, NULL, 0); /* sat/hue */ - reg_w(dev, 0, 0x20, 0x21ae, NULL, 0); /* saturation */ - reg_w(dev, 0, 0, 0x21a3, NULL, 0); /* gamma */ + reg_w(gspca_dev, 0, 0, 0x21a7, 0); /* brightness */ + reg_w(gspca_dev, 0, 0x20, 0x21a8, 0); /* contrast */ + reg_w(gspca_dev, 0, 0, 0x21ad, 0); /* hue */ + reg_w(gspca_dev, 0, 1, 0x21ac, 0); /* sat/hue */ + reg_w(gspca_dev, 0, 0x20, 0x21ae, 0); /* saturation */ + reg_w(gspca_dev, 0, 0, 0x21a3, 0); /* gamma */ break; case BRIDGE_SPCA536: - reg_w(dev, 0, 0, 0x20f0, NULL, 0); - reg_w(dev, 0, 0x21, 0x20f1, NULL, 0); - reg_w(dev, 0, 0x40, 0x20f5, NULL, 0); - reg_w(dev, 0, 1, 0x20f4, NULL, 0); - reg_w(dev, 0, 0x40, 0x20f6, NULL, 0); - reg_w(dev, 0, 0, 0x2089, NULL, 0); + reg_w(gspca_dev, 0, 0, 0x20f0, 0); + reg_w(gspca_dev, 0, 0x21, 0x20f1, 0); + reg_w(gspca_dev, 0, 0x40, 0x20f5, 0); + reg_w(gspca_dev, 0, 1, 0x20f4, 0); + reg_w(gspca_dev, 0, 0x40, 0x20f6, 0); + reg_w(gspca_dev, 0, 0, 0x2089, 0); break; } if (pollreg) @@ -799,7 +809,6 @@ static int sd_config(struct gspca_dev *gspca_dev, const struct usb_device_id *id) { struct sd *sd = (struct sd *) gspca_dev; - struct usb_device *dev = gspca_dev->dev; struct cam *cam; cam = &gspca_dev->cam; @@ -811,7 +820,7 @@ static int sd_config(struct gspca_dev *gspca_dev, if (sd->subtype == AiptekMiniPenCam13) { /* try to get the firmware as some cam answer 2.0.1.2.2 * and should be a spca504b then overwrite that setting */ - reg_r(dev, 0x20, 0, gspca_dev->usb_buf, 1); + reg_r(gspca_dev, 0x20, 0, 1); switch (gspca_dev->usb_buf[0]) { case 1: break; /* (right bridge/subtype) */ @@ -860,12 +869,12 @@ static int sd_init(struct gspca_dev *gspca_dev) switch (sd->bridge) { case BRIDGE_SPCA504B: - reg_w(dev, 0x1d, 0, 0, NULL, 0); - reg_w(dev, 0, 1, 0x2306, NULL, 0); - reg_w(dev, 0, 0, 0x0d04, NULL, 0); - reg_w(dev, 0, 0, 0x2000, NULL, 0); - reg_w(dev, 0, 0x13, 0x2301, NULL, 0); - reg_w(dev, 0, 0, 0x2306, NULL, 0); + reg_w(gspca_dev, 0x1d, 0, 0, 0); + reg_w(gspca_dev, 0, 1, 0x2306, 0); + reg_w(gspca_dev, 0, 0, 0x0d04, 0); + reg_w(gspca_dev, 0, 0, 0x2000, 0); + reg_w(gspca_dev, 0, 0x13, 0x2301, 0); + reg_w(gspca_dev, 0, 0, 0x2306, 0); /* fall thru */ case BRIDGE_SPCA533: rc = spca504B_PollingDataReady(gspca_dev); @@ -873,12 +882,12 @@ static int sd_init(struct gspca_dev *gspca_dev) break; case BRIDGE_SPCA536: spca50x_GetFirmware(gspca_dev); - reg_r(dev, 0x00, 0x5002, gspca_dev->usb_buf, 1); + reg_r(gspca_dev, 0x00, 0x5002, 1); gspca_dev->usb_buf[0] = 0; - reg_w(dev, 0x24, 0, 0, gspca_dev->usb_buf, 1); - reg_r(dev, 0x24, 0, gspca_dev->usb_buf, 1); + reg_w(gspca_dev, 0x24, 0, 0, 1); + reg_r(gspca_dev, 0x24, 0, 1); rc = spca504B_PollingDataReady(gspca_dev); - reg_w(dev, 0x34, 0, 0, NULL, 0); + reg_w(gspca_dev, 0x34, 0, 0, 0); spca504B_WaitCmdStatus(gspca_dev); break; case BRIDGE_SPCA504C: /* pccam600 */ @@ -971,12 +980,12 @@ static void sd_start(struct gspca_dev *gspca_dev) /* case BRIDGE_SPCA536: */ if (sd->subtype == MegapixV4 || sd->subtype == LogitechClickSmart820) { - reg_w(dev, 0xf0, 0, 0, NULL, 0); + reg_w(gspca_dev, 0xf0, 0, 0, 0); spca504B_WaitCmdStatus(gspca_dev); - reg_r(dev, 0xf0, 4, NULL, 0); + reg_r(gspca_dev, 0xf0, 4, 0); spca504B_WaitCmdStatus(gspca_dev); } else { - reg_w(dev, 0x31, 0, 4, NULL, 0); + reg_w(gspca_dev, 0x31, 0, 4, 0); spca504B_WaitCmdStatus(gspca_dev); rc = spca504B_PollingDataReady(gspca_dev); } @@ -1045,7 +1054,7 @@ static void sd_stopN(struct gspca_dev *gspca_dev) /* case BRIDGE_SPCA533: */ /* case BRIDGE_SPCA536: */ /* case BRIDGE_SPCA504B: */ - reg_w(dev, 0x31, 0, 0, NULL, 0); + reg_w(gspca_dev, 0x31, 0, 0, 0); spca504B_WaitCmdStatus(gspca_dev); spca504B_PollingDataReady(gspca_dev); break; diff --git a/drivers/media/video/gspca/t613.c b/drivers/media/video/gspca/t613.c index 81b175e..f034c74 100644 --- a/drivers/media/video/gspca/t613.c +++ b/drivers/media/video/gspca/t613.c @@ -391,7 +391,7 @@ static void reg_w(struct gspca_dev *gspca_dev, NULL, 0, 500); return; } - if (len <= sizeof gspca_dev->usb_buf) { + if (len <= USB_BUF_SZ) { memcpy(gspca_dev->usb_buf, buffer, len); usb_control_msg(gspca_dev->dev, usb_sndctrlpipe(gspca_dev->dev, 0), -- cgit v0.10.2 From 271315a9b4363ed884024022f2cf799344548e8f Mon Sep 17 00:00:00 2001 From: Hans de Goede Date: Wed, 3 Sep 2008 17:12:19 -0300 Subject: V4L/DVB (8830): gspca: Move some probe code to the new init function. Signed-off-by: Hans de Goede Signed-off-by: Jean-Francois Moine Signed-off-by: Mauro Carvalho Chehab diff --git a/drivers/media/video/gspca/pac7311.c b/drivers/media/video/gspca/pac7311.c index 723219d..d4be518 100644 --- a/drivers/media/video/gspca/pac7311.c +++ b/drivers/media/video/gspca/pac7311.c @@ -245,7 +245,7 @@ static struct v4l2_pix_format vga_mode[] = { }; /* pac 7302 */ -static const __u8 probe_7302[] = { +static const __u8 init_7302[] = { /* index,value */ 0xff, 0x01, /* page 1 */ 0x78, 0x00, /* deactivate */ @@ -341,7 +341,7 @@ static const __u8 page3_7302[] = { }; /* pac 7311 */ -static const __u8 probe_7311[] = { +static const __u8 init_7311[] = { 0x78, 0x40, /* Bit_0=start stream, Bit_6=LED */ 0x78, 0x40, /* Bit_0=start stream, Bit_6=LED */ 0x78, 0x44, /* Bit_0=start stream, Bit_6=LED */ @@ -503,14 +503,10 @@ static int sd_config(struct gspca_dev *gspca_dev, sd->sensor = id->driver_info; if (sd->sensor == SENSOR_PAC7302) { PDEBUG(D_CONF, "Find Sensor PAC7302"); - reg_w_seq(gspca_dev, probe_7302, sizeof probe_7302); - cam->cam_mode = &vga_mode[2]; /* only 640x480 */ cam->nmodes = 1; } else { PDEBUG(D_CONF, "Find Sensor PAC7311"); - reg_w_seq(gspca_dev, probe_7311, sizeof probe_7311); - cam->cam_mode = vga_mode; cam->nmodes = ARRAY_SIZE(vga_mode); gspca_dev->ctrl_dis = (1 << BRIGHTNESS_IDX) @@ -669,6 +665,13 @@ static void sethvflip(struct gspca_dev *gspca_dev) /* this function is called at probe and resume time */ static int sd_init(struct gspca_dev *gspca_dev) { + struct sd *sd = (struct sd *) gspca_dev; + + if (sd->sensor == SENSOR_PAC7302) + reg_w_seq(gspca_dev, init_7302, sizeof init_7302); + else + reg_w_seq(gspca_dev, init_7311, sizeof init_7311); + return 0; } diff --git a/drivers/media/video/gspca/sonixb.c b/drivers/media/video/gspca/sonixb.c index 162beb3..6026080 100644 --- a/drivers/media/video/gspca/sonixb.c +++ b/drivers/media/video/gspca/sonixb.c @@ -736,7 +736,6 @@ static int sd_config(struct gspca_dev *gspca_dev, struct sd *sd = (struct sd *) gspca_dev; struct cam *cam; int sif = 0; - const __u8 stop = 0x09; /* Disable stream turn of LED */ reg_r(gspca_dev, 0x00); if (gspca_dev->usb_buf[0] != 0x10) @@ -773,15 +772,16 @@ static int sd_config(struct gspca_dev *gspca_dev, sd->autogain = AUTOGAIN_DEF; sd->freq = FREQ_DEF; - /* Disable stream turn of LED */ - reg_w(gspca_dev, 0x01, &stop, 1); - return 0; } /* this function is called at probe and resume time */ static int sd_init(struct gspca_dev *gspca_dev) { + const __u8 stop = 0x09; /* Disable stream turn of LED */ + + reg_w(gspca_dev, 0x01, &stop, 1); + return 0; } -- cgit v0.10.2 From 222a07ffd8e280b1bf4a6f7edab8b6fa27a5455a Mon Sep 17 00:00:00 2001 From: Hans de Goede Date: Wed, 3 Sep 2008 17:12:20 -0300 Subject: V4L/DVB (8831): gspca: Resolve webcam conflicts between some drivers. -remove USB-id's from zc0301 for cams for which zc0301.c does not support the sensor -remove USB-id's from sn9c102 for cams where sn9c102 does not support the bridge sensor combination -no longer make inclusion of usb id's removed from zc0301 and sn9c102 conditional in gspca -fix conditional inclusion of USB-id's in gspca to also work when the conflicting drivers are build as a module -add a number of USB-id's to gspca from various windows .inf files: 0c45:608f from generic sonix sn9c103 inf file (+ ov7630 which we support) 041e:4022 from creative webcam nx pro, same as already supported 041e:401e 0ac8:0301 from generic zc0301 driver which supports many sensors 10fd:804d from typhoon webshot driver (also FlyCAM-USB 300 plus) Signed-off-by: Hans de Goede Signed-off-by: Jean-Francois Moine Signed-off-by: Mauro Carvalho Chehab diff --git a/drivers/media/video/gspca/etoms.c b/drivers/media/video/gspca/etoms.c index 9eb6adb..4ff0e38 100644 --- a/drivers/media/video/gspca/etoms.c +++ b/drivers/media/video/gspca/etoms.c @@ -897,7 +897,7 @@ static struct sd_desc sd_desc = { /* -- module initialisation -- */ static __devinitdata struct usb_device_id device_table[] = { {USB_DEVICE(0x102c, 0x6151), .driver_info = SENSOR_PAS106}, -#ifndef CONFIG_USB_ET61X251 +#if !defined CONFIG_USB_ET61X251 && !defined CONFIG_USB_ET61X251_MODULE {USB_DEVICE(0x102c, 0x6251), .driver_info = SENSOR_TAS5130CXX}, #endif {} diff --git a/drivers/media/video/gspca/sonixb.c b/drivers/media/video/gspca/sonixb.c index 6026080..f30e6ec 100644 --- a/drivers/media/video/gspca/sonixb.c +++ b/drivers/media/video/gspca/sonixb.c @@ -1153,7 +1153,7 @@ static const struct sd_desc sd_desc = { #define NO_BRIGHTNESS (1 << BRIGHTNESS_IDX) static __devinitdata struct usb_device_id device_table[] = { -#ifndef CONFIG_USB_SN9C102 +#if !defined CONFIG_USB_SN9C102 && !defined CONFIG_USB_SN9C102_MODULE {USB_DEVICE(0x0c45, 0x6001), /* SN9C102 */ SFCI(TAS5110, F_GAIN|F_SIF, NO_BRIGHTNESS|NO_FREQ, 0)}, {USB_DEVICE(0x0c45, 0x6005), /* SN9C101 */ @@ -1167,7 +1167,7 @@ static __devinitdata struct usb_device_id device_table[] = { #endif {USB_DEVICE(0x0c45, 0x6011), /* SN9C101 - SN9C101G */ SFCI(OV6650, F_GAIN|F_SIF, 0, 0x60)}, -#ifndef CONFIG_USB_SN9C102 +#if !defined CONFIG_USB_SN9C102 && !defined CONFIG_USB_SN9C102_MODULE {USB_DEVICE(0x0c45, 0x6019), /* SN9C101 */ SFCI(OV7630, F_GAIN, 0, 0x21)}, {USB_DEVICE(0x0c45, 0x6024), /* SN9C102 */ @@ -1180,10 +1180,14 @@ static __devinitdata struct usb_device_id device_table[] = { SFCI(PAS106, F_SIF, NO_EXPO|NO_FREQ, 0)}, {USB_DEVICE(0x0c45, 0x602c), /* SN9C102 */ SFCI(OV7630, F_GAIN, 0, 0x21)}, +#endif {USB_DEVICE(0x0c45, 0x602d), /* SN9C102 */ SFCI(HV7131R, 0, NO_EXPO|NO_FREQ, 0)}, +#if !defined CONFIG_USB_SN9C102 && !defined CONFIG_USB_SN9C102_MODULE {USB_DEVICE(0x0c45, 0x602e), /* SN9C102 */ SFCI(OV7630, F_GAIN, 0, 0x21)}, + {USB_DEVICE(0x0c45, 0x608f), /* SN9C103 */ + SFCI(OV7630, F_GAIN|F_H18, 0, 0x21)}, {USB_DEVICE(0x0c45, 0x60af), /* SN9C103 */ SFCI(PAS202, F_H18, NO_EXPO|NO_FREQ, 0)}, {USB_DEVICE(0x0c45, 0x60b0), /* SN9C103 */ diff --git a/drivers/media/video/gspca/sonixj.c b/drivers/media/video/gspca/sonixj.c index 5697959..d75b1d2 100644 --- a/drivers/media/video/gspca/sonixj.c +++ b/drivers/media/video/gspca/sonixj.c @@ -1556,7 +1556,7 @@ static const struct sd_desc sd_desc = { | (SENSOR_ ## sensor << 8) \ | (i2c_addr) static const __devinitdata struct usb_device_id device_table[] = { -#ifndef CONFIG_USB_SN9C102 +#if !defined CONFIG_USB_SN9C102 && !defined CONFIG_USB_SN9C102_MODULE {USB_DEVICE(0x0458, 0x7025), BSI(SN9C120, MI0360, 0x5d)}, {USB_DEVICE(0x045e, 0x00f5), BSI(SN9C105, OV7660, 0x21)}, {USB_DEVICE(0x045e, 0x00f7), BSI(SN9C105, OV7660, 0x21)}, @@ -1589,9 +1589,11 @@ static const __devinitdata struct usb_device_id device_table[] = { {USB_DEVICE(0x0c45, 0x612c), BSI(SN9C110, MO4000, 0x21)}, {USB_DEVICE(0x0c45, 0x612e), BSI(SN9C110, OV7630, 0x21)}, /* {USB_DEVICE(0x0c45, 0x612f), BSI(SN9C110, ICM105C, 0x??)}, */ -#ifndef CONFIG_USB_SN9C102 +#if !defined CONFIG_USB_SN9C102 && !defined CONFIG_USB_SN9C102_MODULE {USB_DEVICE(0x0c45, 0x6130), BSI(SN9C120, MI0360, 0x5d)}, +#endif {USB_DEVICE(0x0c45, 0x6138), BSI(SN9C120, MO4000, 0x21)}, +#if !defined CONFIG_USB_SN9C102 && !defined CONFIG_USB_SN9C102_MODULE /* {USB_DEVICE(0x0c45, 0x613a), BSI(SN9C120, OV7648, 0x??)}, */ {USB_DEVICE(0x0c45, 0x613b), BSI(SN9C120, OV7660, 0x21)}, {USB_DEVICE(0x0c45, 0x613c), BSI(SN9C120, HV7131R, 0x11)}, diff --git a/drivers/media/video/gspca/zc3xx.c b/drivers/media/video/gspca/zc3xx.c index f4239b4..8d7c27e 100644 --- a/drivers/media/video/gspca/zc3xx.c +++ b/drivers/media/video/gspca/zc3xx.c @@ -7508,26 +7508,21 @@ static const struct sd_desc sd_desc = { static const __devinitdata struct usb_device_id device_table[] = { {USB_DEVICE(0x041e, 0x041e)}, -#ifndef CONFIG_USB_ZC0301 {USB_DEVICE(0x041e, 0x4017)}, {USB_DEVICE(0x041e, 0x401c), .driver_info = SENSOR_PAS106}, {USB_DEVICE(0x041e, 0x401e)}, {USB_DEVICE(0x041e, 0x401f)}, -#endif + {USB_DEVICE(0x041e, 0x4022)}, {USB_DEVICE(0x041e, 0x4029)}, -#ifndef CONFIG_USB_ZC0301 {USB_DEVICE(0x041e, 0x4034), .driver_info = SENSOR_PAS106}, {USB_DEVICE(0x041e, 0x4035), .driver_info = SENSOR_PAS106}, {USB_DEVICE(0x041e, 0x4036)}, {USB_DEVICE(0x041e, 0x403a)}, -#endif {USB_DEVICE(0x041e, 0x4051), .driver_info = SENSOR_TAS5130C_VF0250}, {USB_DEVICE(0x041e, 0x4053), .driver_info = SENSOR_TAS5130C_VF0250}, -#ifndef CONFIG_USB_ZC0301 {USB_DEVICE(0x0458, 0x7007)}, {USB_DEVICE(0x0458, 0x700c)}, {USB_DEVICE(0x0458, 0x700f)}, -#endif {USB_DEVICE(0x0461, 0x0a00)}, {USB_DEVICE(0x046d, 0x08a0)}, {USB_DEVICE(0x046d, 0x08a1)}, @@ -7539,7 +7534,7 @@ static const __devinitdata struct usb_device_id device_table[] = { {USB_DEVICE(0x046d, 0x08aa)}, {USB_DEVICE(0x046d, 0x08ac)}, {USB_DEVICE(0x046d, 0x08ad)}, -#ifndef CONFIG_USB_ZC0301 +#if !defined CONFIG_USB_ZC0301 && !defined CONFIG_USB_ZC0301_MODULE {USB_DEVICE(0x046d, 0x08ae)}, #endif {USB_DEVICE(0x046d, 0x08af)}, @@ -7554,22 +7549,20 @@ static const __devinitdata struct usb_device_id device_table[] = { {USB_DEVICE(0x0471, 0x032d), .driver_info = SENSOR_PAS106}, {USB_DEVICE(0x0471, 0x032e), .driver_info = SENSOR_PAS106}, {USB_DEVICE(0x055f, 0xc005)}, -#ifndef CONFIG_USB_ZC0301 {USB_DEVICE(0x055f, 0xd003)}, {USB_DEVICE(0x055f, 0xd004)}, -#endif {USB_DEVICE(0x0698, 0x2003)}, + {USB_DEVICE(0x0ac8, 0x0301), .driver_info = SENSOR_PAS106}, {USB_DEVICE(0x0ac8, 0x0302)}, -#ifndef CONFIG_USB_ZC0301 {USB_DEVICE(0x0ac8, 0x301b)}, +#if !defined CONFIG_USB_ZC0301 && !defined CONFIG_USB_ZC0301_MODULE {USB_DEVICE(0x0ac8, 0x303b)}, #endif {USB_DEVICE(0x0ac8, 0x305b), .driver_info = SENSOR_TAS5130C_VF0250}, -#ifndef CONFIG_USB_ZC0301 {USB_DEVICE(0x0ac8, 0x307b)}, {USB_DEVICE(0x10fd, 0x0128)}, + {USB_DEVICE(0x10fd, 0x804d)}, {USB_DEVICE(0x10fd, 0x8050)}, -#endif {} /* end of entry */ }; #undef DVNAME diff --git a/drivers/media/video/sn9c102/sn9c102_devtable.h b/drivers/media/video/sn9c102/sn9c102_devtable.h index 6ff489b..85499a3 100644 --- a/drivers/media/video/sn9c102/sn9c102_devtable.h +++ b/drivers/media/video/sn9c102/sn9c102_devtable.h @@ -45,6 +45,7 @@ static const struct usb_device_id sn9c102_id_table[] = { { SN9C102_USB_DEVICE(0x0c45, 0x6007, BRIDGE_SN9C102), }, { SN9C102_USB_DEVICE(0x0c45, 0x6009, BRIDGE_SN9C102), }, { SN9C102_USB_DEVICE(0x0c45, 0x600d, BRIDGE_SN9C102), }, +/* { SN9C102_USB_DEVICE(0x0c45, 0x6011, BRIDGE_SN9C102), }, OV6650 */ { SN9C102_USB_DEVICE(0x0c45, 0x6019, BRIDGE_SN9C102), }, { SN9C102_USB_DEVICE(0x0c45, 0x6024, BRIDGE_SN9C102), }, { SN9C102_USB_DEVICE(0x0c45, 0x6025, BRIDGE_SN9C102), }, @@ -53,24 +54,24 @@ static const struct usb_device_id sn9c102_id_table[] = { { SN9C102_USB_DEVICE(0x0c45, 0x602a, BRIDGE_SN9C102), }, { SN9C102_USB_DEVICE(0x0c45, 0x602b, BRIDGE_SN9C102), }, { SN9C102_USB_DEVICE(0x0c45, 0x602c, BRIDGE_SN9C102), }, - { SN9C102_USB_DEVICE(0x0c45, 0x602d, BRIDGE_SN9C102), }, +/* { SN9C102_USB_DEVICE(0x0c45, 0x602d, BRIDGE_SN9C102), }, HV7131R */ { SN9C102_USB_DEVICE(0x0c45, 0x602e, BRIDGE_SN9C102), }, { SN9C102_USB_DEVICE(0x0c45, 0x6030, BRIDGE_SN9C102), }, /* SN9C103 */ { SN9C102_USB_DEVICE(0x0c45, 0x6080, BRIDGE_SN9C103), }, { SN9C102_USB_DEVICE(0x0c45, 0x6082, BRIDGE_SN9C103), }, - { SN9C102_USB_DEVICE(0x0c45, 0x6083, BRIDGE_SN9C103), }, +/* { SN9C102_USB_DEVICE(0x0c45, 0x6083, BRIDGE_SN9C103), }, HY7131D/E */ { SN9C102_USB_DEVICE(0x0c45, 0x6088, BRIDGE_SN9C103), }, { SN9C102_USB_DEVICE(0x0c45, 0x608a, BRIDGE_SN9C103), }, { SN9C102_USB_DEVICE(0x0c45, 0x608b, BRIDGE_SN9C103), }, { SN9C102_USB_DEVICE(0x0c45, 0x608c, BRIDGE_SN9C103), }, - { SN9C102_USB_DEVICE(0x0c45, 0x608e, BRIDGE_SN9C103), }, +/* { SN9C102_USB_DEVICE(0x0c45, 0x608e, BRIDGE_SN9C103), }, CISVF10 */ { SN9C102_USB_DEVICE(0x0c45, 0x608f, BRIDGE_SN9C103), }, { SN9C102_USB_DEVICE(0x0c45, 0x60a0, BRIDGE_SN9C103), }, { SN9C102_USB_DEVICE(0x0c45, 0x60a2, BRIDGE_SN9C103), }, { SN9C102_USB_DEVICE(0x0c45, 0x60a3, BRIDGE_SN9C103), }, - { SN9C102_USB_DEVICE(0x0c45, 0x60a8, BRIDGE_SN9C103), }, - { SN9C102_USB_DEVICE(0x0c45, 0x60aa, BRIDGE_SN9C103), }, +/* { SN9C102_USB_DEVICE(0x0c45, 0x60a8, BRIDGE_SN9C103), }, PAS106 */ +/* { SN9C102_USB_DEVICE(0x0c45, 0x60aa, BRIDGE_SN9C103), }, TAS5130 */ { SN9C102_USB_DEVICE(0x0c45, 0x60ab, BRIDGE_SN9C103), }, { SN9C102_USB_DEVICE(0x0c45, 0x60ac, BRIDGE_SN9C103), }, { SN9C102_USB_DEVICE(0x0c45, 0x60ae, BRIDGE_SN9C103), }, @@ -105,7 +106,7 @@ static const struct usb_device_id sn9c102_id_table[] = { { SN9C102_USB_DEVICE(0x0c45, 0x6108, BRIDGE_SN9C120), }, { SN9C102_USB_DEVICE(0x0c45, 0x610f, BRIDGE_SN9C120), }, { SN9C102_USB_DEVICE(0x0c45, 0x6130, BRIDGE_SN9C120), }, - { SN9C102_USB_DEVICE(0x0c45, 0x6138, BRIDGE_SN9C120), }, +/* { SN9C102_USB_DEVICE(0x0c45, 0x6138, BRIDGE_SN9C120), }, MO8000 */ { SN9C102_USB_DEVICE(0x0c45, 0x613a, BRIDGE_SN9C120), }, { SN9C102_USB_DEVICE(0x0c45, 0x613b, BRIDGE_SN9C120), }, { SN9C102_USB_DEVICE(0x0c45, 0x613c, BRIDGE_SN9C120), }, diff --git a/drivers/media/video/zc0301/zc0301_sensor.h b/drivers/media/video/zc0301/zc0301_sensor.h index 70fe6fc..b0cd49c 100644 --- a/drivers/media/video/zc0301/zc0301_sensor.h +++ b/drivers/media/video/zc0301/zc0301_sensor.h @@ -60,27 +60,8 @@ zc0301_attach_sensor(struct zc0301_device* cam, struct zc0301_sensor* sensor); #define ZC0301_ID_TABLE \ static const struct usb_device_id zc0301_id_table[] = { \ - { ZC0301_USB_DEVICE(0x041e, 0x4017, 0xff), }, /* ICM105 */ \ - { ZC0301_USB_DEVICE(0x041e, 0x401c, 0xff), }, /* PAS106 */ \ - { ZC0301_USB_DEVICE(0x041e, 0x401e, 0xff), }, /* HV7131 */ \ - { ZC0301_USB_DEVICE(0x041e, 0x401f, 0xff), }, /* TAS5130 */ \ - { ZC0301_USB_DEVICE(0x041e, 0x4022, 0xff), }, \ - { ZC0301_USB_DEVICE(0x041e, 0x4034, 0xff), }, /* PAS106 */ \ - { ZC0301_USB_DEVICE(0x041e, 0x4035, 0xff), }, /* PAS106 */ \ - { ZC0301_USB_DEVICE(0x041e, 0x4036, 0xff), }, /* HV7131 */ \ - { ZC0301_USB_DEVICE(0x041e, 0x403a, 0xff), }, /* HV7131 */ \ - { ZC0301_USB_DEVICE(0x0458, 0x7007, 0xff), }, /* TAS5130 */ \ - { ZC0301_USB_DEVICE(0x0458, 0x700c, 0xff), }, /* TAS5130 */ \ - { ZC0301_USB_DEVICE(0x0458, 0x700f, 0xff), }, /* TAS5130 */ \ { ZC0301_USB_DEVICE(0x046d, 0x08ae, 0xff), }, /* PAS202 */ \ - { ZC0301_USB_DEVICE(0x055f, 0xd003, 0xff), }, /* TAS5130 */ \ - { ZC0301_USB_DEVICE(0x055f, 0xd004, 0xff), }, /* TAS5130 */ \ - { ZC0301_USB_DEVICE(0x0ac8, 0x0301, 0xff), }, \ - { ZC0301_USB_DEVICE(0x0ac8, 0x301b, 0xff), }, /* PB-0330/HV7131 */ \ { ZC0301_USB_DEVICE(0x0ac8, 0x303b, 0xff), }, /* PB-0330 */ \ - { ZC0301_USB_DEVICE(0x10fd, 0x0128, 0xff), }, /* TAS5130 */ \ - { ZC0301_USB_DEVICE(0x10fd, 0x8050, 0xff), }, /* TAS5130 */ \ - { ZC0301_USB_DEVICE(0x10fd, 0x804e, 0xff), }, /* TAS5130 */ \ { } \ }; -- cgit v0.10.2 From 20122542df420a31532c8e2b5d4107e9846bac6b Mon Sep 17 00:00:00 2001 From: Jean-Francois Moine Date: Wed, 3 Sep 2008 17:12:20 -0300 Subject: V4L/DVB (8832): gspca: Bad pixelformat of vc0321 webcams. Signed-off-by: Jean-Francois Moine Signed-off-by: Mauro Carvalho Chehab diff --git a/drivers/media/video/gspca/vc032x.c b/drivers/media/video/gspca/vc032x.c index f8c3ff3..bd4c226 100644 --- a/drivers/media/video/gspca/vc032x.c +++ b/drivers/media/video/gspca/vc032x.c @@ -88,12 +88,12 @@ static struct ctrl sd_ctrls[] = { }; static struct v4l2_pix_format vc0321_mode[] = { - {320, 240, V4L2_PIX_FMT_YUV420, V4L2_FIELD_NONE, + {320, 240, V4L2_PIX_FMT_YVYU, V4L2_FIELD_NONE, .bytesperline = 320, .sizeimage = 320 * 240 * 2, .colorspace = V4L2_COLORSPACE_SRGB, .priv = 1}, - {640, 480, V4L2_PIX_FMT_YUV420, V4L2_FIELD_NONE, + {640, 480, V4L2_PIX_FMT_YVYU, V4L2_FIELD_NONE, .bytesperline = 640, .sizeimage = 640 * 480 * 2, .colorspace = V4L2_COLORSPACE_SRGB, diff --git a/include/linux/videodev2.h b/include/linux/videodev2.h index 6c73516..303d93f 100644 --- a/include/linux/videodev2.h +++ b/include/linux/videodev2.h @@ -335,6 +335,7 @@ struct v4l2_pix_format { #define V4L2_PIX_FMT_SPCA561 v4l2_fourcc('S', '5', '6', '1') /* compressed GBRG bayer */ #define V4L2_PIX_FMT_PAC207 v4l2_fourcc('P', '2', '0', '7') /* compressed BGGR bayer */ #define V4L2_PIX_FMT_PJPG v4l2_fourcc('P', 'J', 'P', 'G') /* Pixart 73xx JPEG */ +#define V4L2_PIX_FMT_YVYU v4l2_fourcc('Y', 'V', 'Y', 'U') /* 16 YVU 4:2:2 */ /* * F O R M A T E N U M E R A T I O N -- cgit v0.10.2 From f45f06b648bad82430c64a2e1ad67dc616eb54c6 Mon Sep 17 00:00:00 2001 From: Hans de Goede Date: Wed, 3 Sep 2008 17:12:21 -0300 Subject: V4L/DVB (8833): gspca: Cleanup the sonixb code. -the usb-id table caried several flags which were not usb-id specific but sensor specific, add a sensor_data array and move these flag there -fr_h_sz was being abused to store and check which bridge was being used instead add a bridge member to the sd struct -now that we have a sensor_data table use that to store pointers to init_sequences instead of using switch cases on sd->sensor Signed-off-by: Hans de Goede Signed-off-by: Jean-Francois Moine Signed-off-by: Mauro Carvalho Chehab diff --git a/drivers/media/video/gspca/sonixb.c b/drivers/media/video/gspca/sonixb.c index f30e6ec..8eaeaa3 100644 --- a/drivers/media/video/gspca/sonixb.c +++ b/drivers/media/video/gspca/sonixb.c @@ -41,8 +41,12 @@ struct sd { unsigned char frames_to_drop; unsigned char freq; /* light freq filter setting */ - unsigned char fr_h_sz; /* size of frame header */ - char sensor; /* Type of image sensor chip */ + __u8 bridge; /* Type of bridge */ +#define BRIDGE_101 0 +#define BRIDGE_102 0 /* We make no difference between 101 and 102 */ +#define BRIDGE_103 1 + + __u8 sensor; /* Type of image sensor chip */ #define SENSOR_HV7131R 0 #define SENSOR_OV6650 1 #define SENSOR_OV7630 2 @@ -50,15 +54,31 @@ struct sd { #define SENSOR_PAS202 4 #define SENSOR_TAS5110 5 #define SENSOR_TAS5130CXX 6 - char sensor_has_gain; - __u8 sensor_addr; __u8 reg11; }; -/* flags used in the device id table */ +typedef const __u8 sensor_init_t[8]; + +struct sensor_data { + const __u8 *bridge_init[2]; + int bridge_init_size[2]; + sensor_init_t *sensor_init; + int sensor_init_size; + sensor_init_t *sensor_bridge_init[2]; + int sensor_bridge_init_size[2]; + int flags; + unsigned ctrl_dis; + __u8 sensor_addr; +}; + +/* sensor_data flags */ #define F_GAIN 0x01 /* has gain */ #define F_SIF 0x02 /* sif or vga */ -#define F_H18 0x04 /* long (18 b) or short (12 b) frame header */ + +/* ctrl_dis helper macros */ +#define NO_EXPO ((1 << EXPOSURE_IDX) | (1 << AUTOGAIN_IDX)) +#define NO_FREQ (1 << FREQ_IDX) +#define NO_BRIGHTNESS (1 << BRIGHTNESS_IDX) #define COMP2 0x8f #define COMP 0xc7 /* 0x87 //0x07 */ @@ -69,6 +89,18 @@ struct sd { #define SYS_CLK 0x04 +#define SENS(bridge_1, bridge_3, sensor, sensor_1, \ + sensor_3, _flags, _ctrl_dis, _sensor_addr) \ +{ \ + .bridge_init = { bridge_1, bridge_3 }, \ + .bridge_init_size = { sizeof(bridge_1), sizeof(bridge_3) }, \ + .sensor_init = sensor, \ + .sensor_init_size = sizeof(sensor), \ + .sensor_bridge_init = { sensor_1, sensor_3,}, \ + .sensor_bridge_init_size = { sizeof(sensor_1), sizeof(sensor_3)}, \ + .flags = _flags, .ctrl_dis = _ctrl_dis, .sensor_addr = _sensor_addr \ +} + /* We calculate the autogain at the end of the transfer of a frame, at this moment a frame with the old settings is being transmitted, and a frame is being captured with the old settings. So if we adjust the autogain we must @@ -219,7 +251,7 @@ static const __u8 hv7131_sensor_init[][8] = { static const __u8 initOv6650[] = { 0x44, 0x44, 0x00, 0x00, 0x00, 0x00, 0x00, 0x80, 0x60, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x02, 0x01, 0x0a, 0x16, 0x12, 0x68, 0x0b, + 0x00, 0x02, 0x01, 0x0a, 0x16, 0x12, 0x68, 0x8b, 0x10, 0x1d, 0x10, 0x00, 0x06, 0x1f, 0x00 }; static const __u8 ov6650_sensor_init[][8] = @@ -260,7 +292,7 @@ static const __u8 initOv7630[] = { 0x21, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* r09 .. r10 */ 0x00, 0x02, 0x01, 0x0a, /* r11 .. r14 */ 0x28, 0x1e, /* H & V sizes r15 .. r16 */ - 0x68, COMP1, MCK_INIT1, /* r17 .. r19 */ + 0x68, COMP2, MCK_INIT1, /* r17 .. r19 */ 0x1d, 0x10, 0x02, 0x03, 0x0f, 0x0c /* r1a .. r1f */ }; static const __u8 initOv7630_3[] = { @@ -295,47 +327,65 @@ static const __u8 ov7630_sensor_init[][8] = { {0xd0, 0x21, 0x17, 0x1c, 0xbd, 0x06, 0xf6, 0x10}, }; +static const __u8 ov7630_sensor_init_3[][8] = { + {0xa0, 0x21, 0x13, 0x80, 0x00, 0x00, 0x00, 0x10}, +}; + static const __u8 initPas106[] = { 0x04, 0x03, 0x00, 0x00, 0x00, 0x00, 0x00, 0x81, 0x40, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x05, 0x01, 0x00, - 0x16, 0x12, 0x28, COMP1, MCK_INIT1, + 0x16, 0x12, 0x24, COMP1, MCK_INIT1, 0x18, 0x10, 0x04, 0x03, 0x11, 0x0c }; /* compression 0x86 mckinit1 0x2b */ -static const __u8 pas106_data[][2] = { - {0x02, 0x04}, /* Pixel Clock Divider 6 */ - {0x03, 0x13}, /* Frame Time MSB */ -/* {0x03, 0x12}, * Frame Time MSB */ - {0x04, 0x06}, /* Frame Time LSB */ -/* {0x04, 0x05}, * Frame Time LSB */ - {0x05, 0x65}, /* Shutter Time Line Offset */ -/* {0x05, 0x6d}, * Shutter Time Line Offset */ -/* {0x06, 0xb1}, * Shutter Time Pixel Offset */ - {0x06, 0xcd}, /* Shutter Time Pixel Offset */ - {0x07, 0xc1}, /* Black Level Subtract Sign */ -/* {0x07, 0x00}, * Black Level Subtract Sign */ - {0x08, 0x06}, /* Black Level Subtract Level */ - {0x08, 0x06}, /* Black Level Subtract Level */ -/* {0x08, 0x01}, * Black Level Subtract Level */ - {0x09, 0x05}, /* Color Gain B Pixel 5 a */ - {0x0a, 0x04}, /* Color Gain G1 Pixel 1 5 */ - {0x0b, 0x04}, /* Color Gain G2 Pixel 1 0 5 */ - {0x0c, 0x05}, /* Color Gain R Pixel 3 1 */ - {0x0d, 0x00}, /* Color GainH Pixel */ - {0x0e, 0x0e}, /* Global Gain */ - {0x0f, 0x00}, /* Contrast */ - {0x10, 0x06}, /* H&V synchro polarity */ - {0x11, 0x06}, /* ?default */ - {0x12, 0x06}, /* DAC scale */ - {0x14, 0x02}, /* ?default */ - {0x13, 0x01}, /* Validate Settings */ +static const __u8 pas106_sensor_init[][8] = { + /* Pixel Clock Divider 6 */ + { 0xa1, 0x40, 0x02, 0x04, 0x00, 0x00, 0x00, 0x14 }, + /* Frame Time MSB (also seen as 0x12) */ + { 0xa1, 0x40, 0x03, 0x13, 0x00, 0x00, 0x00, 0x14 }, + /* Frame Time LSB (also seen as 0x05) */ + { 0xa1, 0x40, 0x04, 0x06, 0x00, 0x00, 0x00, 0x14 }, + /* Shutter Time Line Offset (also seen as 0x6d) */ + { 0xa1, 0x40, 0x05, 0x65, 0x00, 0x00, 0x00, 0x14 }, + /* Shutter Time Pixel Offset (also seen as 0xb1) */ + { 0xa1, 0x40, 0x06, 0xcd, 0x00, 0x00, 0x00, 0x14 }, + /* Black Level Subtract Sign (also seen 0x00) */ + { 0xa1, 0x40, 0x07, 0xc1, 0x00, 0x00, 0x00, 0x14 }, + /* Black Level Subtract Level (also seen 0x01) */ + { 0xa1, 0x40, 0x08, 0x06, 0x00, 0x00, 0x00, 0x14 }, + { 0xa1, 0x40, 0x08, 0x06, 0x00, 0x00, 0x00, 0x14 }, + /* Color Gain B Pixel 5 a */ + { 0xa1, 0x40, 0x09, 0x05, 0x00, 0x00, 0x00, 0x14 }, + /* Color Gain G1 Pixel 1 5 */ + { 0xa1, 0x40, 0x0a, 0x04, 0x00, 0x00, 0x00, 0x14 }, + /* Color Gain G2 Pixel 1 0 5 */ + { 0xa1, 0x40, 0x0b, 0x04, 0x00, 0x00, 0x00, 0x14 }, + /* Color Gain R Pixel 3 1 */ + { 0xa1, 0x40, 0x0c, 0x05, 0x00, 0x00, 0x00, 0x14 }, + /* Color GainH Pixel */ + { 0xa1, 0x40, 0x0d, 0x00, 0x00, 0x00, 0x00, 0x14 }, + /* Global Gain */ + { 0xa1, 0x40, 0x0e, 0x0e, 0x00, 0x00, 0x00, 0x14 }, + /* Contrast */ + { 0xa1, 0x40, 0x0f, 0x00, 0x00, 0x00, 0x00, 0x14 }, + /* H&V synchro polarity */ + { 0xa1, 0x40, 0x10, 0x06, 0x00, 0x00, 0x00, 0x14 }, + /* ?default */ + { 0xa1, 0x40, 0x11, 0x06, 0x00, 0x00, 0x00, 0x14 }, + /* DAC scale */ + { 0xa1, 0x40, 0x12, 0x06, 0x00, 0x00, 0x00, 0x14 }, + /* ?default */ + { 0xa1, 0x40, 0x14, 0x02, 0x00, 0x00, 0x00, 0x14 }, + /* Validate Settings */ + { 0xa1, 0x40, 0x13, 0x01, 0x00, 0x00, 0x00, 0x14 }, }; + static const __u8 initPas202[] = { 0x44, 0x44, 0x21, 0x30, 0x00, 0x00, 0x00, 0x80, 0x40, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x07, 0x03, 0x0a, /* 6 */ - 0x28, 0x1e, 0x28, 0x89, 0x30, + 0x28, 0x1e, 0x28, 0x89, 0x20, 0x00, 0x00, 0x02, 0x03, 0x0f, 0x0c }; static const __u8 pas202_sensor_init[][8] = { @@ -390,6 +440,21 @@ static const __u8 tas5130_sensor_init[][8] = { {0x30, 0x11, 0x02, 0x20, 0x70, 0x00, 0x00, 0x10}, }; +struct sensor_data sensor_data[] = { +SENS(initHv7131, NULL, hv7131_sensor_init, NULL, NULL, 0, NO_EXPO|NO_FREQ, 0), +SENS(initOv6650, NULL, ov6650_sensor_init, NULL, NULL, F_GAIN|F_SIF, 0, 0x60), +SENS(initOv7630, initOv7630_3, ov7630_sensor_init, NULL, ov7630_sensor_init_3, + F_GAIN, 0, 0x21), +SENS(initPas106, NULL, pas106_sensor_init, NULL, NULL, F_SIF, NO_EXPO|NO_FREQ, + 0), +SENS(initPas202, initPas202, pas202_sensor_init, NULL, NULL, 0, + NO_EXPO|NO_FREQ, 0), +SENS(initTas5110, NULL, tas5110_sensor_init, NULL, NULL, F_GAIN|F_SIF, + NO_BRIGHTNESS|NO_FREQ, 0), +SENS(initTas5130, NULL, tas5130_sensor_init, NULL, NULL, 0, NO_EXPO|NO_FREQ, + 0), +}; + /* get one byte in gspca_dev->usb_buf */ static void reg_r(struct gspca_dev *gspca_dev, __u16 value) @@ -468,7 +533,7 @@ static void setbrightness(struct gspca_dev *gspca_dev) {0xa0, 0x00, 0x06, 0x00, 0x00, 0x00, 0x00, 0x10}; /* change reg 0x06 */ - i2cOV[1] = sd->sensor_addr; + i2cOV[1] = sensor_data[sd->sensor].sensor_addr; i2cOV[3] = sd->brightness; if (i2c_w(gspca_dev, i2cOV) < 0) goto err; @@ -555,7 +620,7 @@ static void setsensorgain(struct gspca_dev *gspca_dev) case SENSOR_OV7630: { __u8 i2c[] = {0xa0, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x10}; - i2c[1] = sd->sensor_addr; + i2c[1] = sensor_data[sd->sensor].sensor_addr; i2c[3] = gain >> 2; if (i2c_w(gspca_dev, i2c) < 0) goto err; @@ -582,7 +647,7 @@ static void setgain(struct gspca_dev *gspca_dev) rgb_value = gain; reg_w(gspca_dev, 0x11, &rgb_value, 1); - if (sd->sensor_has_gain) + if (sensor_data[sd->sensor].flags & F_GAIN) setsensorgain(gspca_dev); } @@ -662,7 +727,7 @@ static void setexposure(struct gspca_dev *gspca_dev) reg10 = reg10_max; /* Write reg 10 and reg11 low nibble */ - i2c[1] = sd->sensor_addr; + i2c[1] = sensor_data[sd->sensor].sensor_addr; i2c[3] = reg10; i2c[4] |= reg11 - 1; @@ -702,7 +767,7 @@ static void setfreq(struct gspca_dev *gspca_dev) ? 0x4f : 0x8a; break; } - i2c[1] = sd->sensor_addr; + i2c[1] = sensor_data[sd->sensor].sensor_addr; if (i2c_w(gspca_dev, i2c) < 0) PDEBUG(D_ERR, "i2c error setfreq"); break; @@ -735,28 +800,19 @@ static int sd_config(struct gspca_dev *gspca_dev, { struct sd *sd = (struct sd *) gspca_dev; struct cam *cam; - int sif = 0; reg_r(gspca_dev, 0x00); if (gspca_dev->usb_buf[0] != 0x10) return -ENODEV; /* copy the webcam info from the device id */ - sd->sensor = (id->driver_info >> 24) & 0xff; - if (id->driver_info & (F_GAIN << 16)) - sd->sensor_has_gain = 1; - if (id->driver_info & (F_SIF << 16)) - sif = 1; - if (id->driver_info & (F_H18 << 16)) - sd->fr_h_sz = 18; /* size of frame header */ - else - sd->fr_h_sz = 12; - gspca_dev->ctrl_dis = (id->driver_info >> 8) & 0xff; - sd->sensor_addr = id->driver_info & 0xff; + sd->sensor = id->driver_info >> 8; + sd->bridge = id->driver_info & 0xff; + gspca_dev->ctrl_dis = sensor_data[sd->sensor].ctrl_dis; cam = &gspca_dev->cam; cam->epaddr = 0x01; - if (!sif) { + if (!(sensor_data[sd->sensor].flags & F_SIF)) { cam->cam_mode = vga_mode; cam->nmodes = ARRAY_SIZE(vga_mode); } else { @@ -785,78 +841,29 @@ static int sd_init(struct gspca_dev *gspca_dev) return 0; } -static void pas106_i2cinit(struct gspca_dev *gspca_dev) -{ - int i; - const __u8 *data; - __u8 i2c1[] = { 0xa1, 0x40, 0x00, 0x00, 0x00, 0x00, 0x00, 0x14 }; - - i = ARRAY_SIZE(pas106_data); - data = pas106_data[0]; - while (--i >= 0) { - memcpy(&i2c1[2], data, 2); - /* copy 2 bytes from the template */ - if (i2c_w(gspca_dev, i2c1) < 0) - PDEBUG(D_ERR, "i2c error pas106"); - data += 2; - } -} - /* -- start the camera -- */ static void sd_start(struct gspca_dev *gspca_dev) { struct sd *sd = (struct sd *) gspca_dev; - int mode, l = 0x1f; + int mode, l; const __u8 *sn9c10x; __u8 reg17_19[3]; - mode = gspca_dev->cam.cam_mode[(int) gspca_dev->curr_mode].priv; + mode = gspca_dev->cam.cam_mode[(int) gspca_dev->curr_mode].priv & 0x07; + sn9c10x = sensor_data[sd->sensor].bridge_init[sd->bridge]; + l = sensor_data[sd->sensor].bridge_init_size[sd->bridge]; + reg17_19[0] = sn9c10x[0x17 - 1]; + reg17_19[1] = sn9c10x[0x18 - 1] | (mode << 4); + reg17_19[2] = sn9c10x[0x19 - 1]; + /* Special cases where reg 17 and or 19 value depends on mode */ switch (sd->sensor) { - case SENSOR_HV7131R: - sn9c10x = initHv7131; - reg17_19[0] = 0x60; - reg17_19[1] = (mode << 4) | 0x8a; - reg17_19[2] = 0x20; - break; - case SENSOR_OV6650: - sn9c10x = initOv6650; - reg17_19[0] = 0x68; - reg17_19[1] = (mode << 4) | 0x8b; - reg17_19[2] = 0x20; - break; - case SENSOR_OV7630: - if (sd->fr_h_sz == 18) { /* SN9C103 */ - sn9c10x = initOv7630_3; - l = sizeof initOv7630_3; - } else - sn9c10x = initOv7630; - reg17_19[0] = 0x68; - reg17_19[1] = (mode << 4) | COMP2; - reg17_19[2] = MCK_INIT1; - break; - case SENSOR_PAS106: - sn9c10x = initPas106; - reg17_19[0] = 0x24; /* 0x28 */ - reg17_19[1] = (mode << 4) | COMP1; - reg17_19[2] = MCK_INIT1; - break; case SENSOR_PAS202: - sn9c10x = initPas202; reg17_19[0] = mode ? 0x24 : 0x20; - reg17_19[1] = (mode << 4) | 0x89; - reg17_19[2] = 0x20; break; - case SENSOR_TAS5110: - sn9c10x = initTas5110; - reg17_19[0] = 0x60; - reg17_19[1] = (mode << 4) | 0x86; - reg17_19[2] = 0x2b; /* 0xf3; */ - break; - default: -/* case SENSOR_TAS5130CXX: */ - sn9c10x = initTas5130; - reg17_19[0] = 0x60; - reg17_19[1] = (mode << 4) | COMP; + case SENSOR_TAS5130CXX: + /* probably not mode specific at all most likely the upper + nibble of 0x19 is exposure (clock divider) just as with + the tas5110, we need someone to test this. */ reg17_19[2] = mode ? 0x23 : 0x43; break; } @@ -867,41 +874,16 @@ static void sd_start(struct gspca_dev *gspca_dev) reg_w(gspca_dev, 0x17, &sn9c10x[0x17 - 1], 1); /* Set the registers from the template */ reg_w(gspca_dev, 0x01, sn9c10x, l); - switch (sd->sensor) { - case SENSOR_HV7131R: - i2c_w_vector(gspca_dev, hv7131_sensor_init, - sizeof hv7131_sensor_init); - break; - case SENSOR_OV6650: - i2c_w_vector(gspca_dev, ov6650_sensor_init, - sizeof ov6650_sensor_init); - break; - case SENSOR_OV7630: - i2c_w_vector(gspca_dev, ov7630_sensor_init, - sizeof ov7630_sensor_init); - if (sd->fr_h_sz == 18) { /* SN9C103 */ - const __u8 i2c[] = { 0xa0, 0x21, 0x13, 0x80, 0x00, - 0x00, 0x00, 0x10 }; - i2c_w(gspca_dev, i2c); - } - break; - case SENSOR_PAS106: - pas106_i2cinit(gspca_dev); - break; - case SENSOR_PAS202: - i2c_w_vector(gspca_dev, pas202_sensor_init, - sizeof pas202_sensor_init); - break; - case SENSOR_TAS5110: - i2c_w_vector(gspca_dev, tas5110_sensor_init, - sizeof tas5110_sensor_init); - break; - default: -/* case SENSOR_TAS5130CXX: */ - i2c_w_vector(gspca_dev, tas5130_sensor_init, - sizeof tas5130_sensor_init); - break; - } + + /* Init the sensor */ + i2c_w_vector(gspca_dev, sensor_data[sd->sensor].sensor_init, + sensor_data[sd->sensor].sensor_init_size); + if (sensor_data[sd->sensor].sensor_bridge_init[sd->bridge]) + i2c_w_vector(gspca_dev, + sensor_data[sd->sensor].sensor_bridge_init[sd->bridge], + sensor_data[sd->sensor].sensor_bridge_init_size[ + sd->bridge]); + /* H_size V_size 0x28, 0x1e -> 640x480. 0x16, 0x12 -> 352x288 */ reg_w(gspca_dev, 0x15, &sn9c10x[0x15 - 1], 2); /* compression register */ @@ -937,10 +919,7 @@ static void sd_start(struct gspca_dev *gspca_dev) static void sd_stopN(struct gspca_dev *gspca_dev) { - __u8 ByteSend; - - ByteSend = 0x09; /* 0X00 */ - reg_w(gspca_dev, 0x01, &ByteSend, 1); + sd_init(gspca_dev); } static void sd_pkt_scan(struct gspca_dev *gspca_dev, @@ -970,15 +949,17 @@ static void sd_pkt_scan(struct gspca_dev *gspca_dev, && data[5 + i] == 0x96) { /* start of frame */ int lum = -1; int pkt_type = LAST_PACKET; + int fr_h_sz = (sd->bridge == BRIDGE_103) ? + 18 : 12; - if (len - i < sd->fr_h_sz) { + if (len - i < fr_h_sz) { PDEBUG(D_STREAM, "packet too short to" " get avg brightness"); - } else if (sd->fr_h_sz == 12) { - lum = data[i + 8] + (data[i + 9] << 8); - } else { + } else if (sd->bridge == BRIDGE_103) { lum = data[i + 9] + (data[i + 10] << 8); + } else { + lum = data[i + 8] + (data[i + 9] << 8); } if (lum == 0) { lum = -1; @@ -993,8 +974,8 @@ static void sd_pkt_scan(struct gspca_dev *gspca_dev, frame = gspca_frame_add(gspca_dev, pkt_type, frame, data, 0); - data += i + sd->fr_h_sz; - len -= i + sd->fr_h_sz; + data += i + fr_h_sz; + len -= i + fr_h_sz; gspca_frame_add(gspca_dev, FIRST_PACKET, frame, data, len); return; @@ -1143,55 +1124,33 @@ static const struct sd_desc sd_desc = { }; /* -- module initialisation -- */ -#define SFCI(sensor, flags, disable_ctrls, i2c_addr) \ - .driver_info = (SENSOR_ ## sensor << 24) \ - | ((flags) << 16) \ - | ((disable_ctrls) << 8) \ - | (i2c_addr) -#define NO_EXPO ((1 << EXPOSURE_IDX) | (1 << AUTOGAIN_IDX)) -#define NO_FREQ (1 << FREQ_IDX) -#define NO_BRIGHTNESS (1 << BRIGHTNESS_IDX) +#define SB(sensor, bridge) \ + .driver_info = (SENSOR_ ## sensor << 8) | BRIDGE_ ## bridge + static __devinitdata struct usb_device_id device_table[] = { #if !defined CONFIG_USB_SN9C102 && !defined CONFIG_USB_SN9C102_MODULE - {USB_DEVICE(0x0c45, 0x6001), /* SN9C102 */ - SFCI(TAS5110, F_GAIN|F_SIF, NO_BRIGHTNESS|NO_FREQ, 0)}, - {USB_DEVICE(0x0c45, 0x6005), /* SN9C101 */ - SFCI(TAS5110, F_GAIN|F_SIF, NO_BRIGHTNESS|NO_FREQ, 0)}, - {USB_DEVICE(0x0c45, 0x6007), /* SN9C101 */ - SFCI(TAS5110, F_GAIN|F_SIF, NO_BRIGHTNESS|NO_FREQ, 0)}, - {USB_DEVICE(0x0c45, 0x6009), /* SN9C101 */ - SFCI(PAS106, F_SIF, NO_EXPO|NO_FREQ, 0)}, - {USB_DEVICE(0x0c45, 0x600d), /* SN9C101 */ - SFCI(PAS106, F_SIF, NO_EXPO|NO_FREQ, 0)}, + {USB_DEVICE(0x0c45, 0x6001), SB(TAS5110, 102)}, + {USB_DEVICE(0x0c45, 0x6005), SB(TAS5110, 101)}, + {USB_DEVICE(0x0c45, 0x6007), SB(TAS5110, 101)}, + {USB_DEVICE(0x0c45, 0x6009), SB(PAS106, 101)}, + {USB_DEVICE(0x0c45, 0x600d), SB(PAS106, 101)}, #endif - {USB_DEVICE(0x0c45, 0x6011), /* SN9C101 - SN9C101G */ - SFCI(OV6650, F_GAIN|F_SIF, 0, 0x60)}, + {USB_DEVICE(0x0c45, 0x6011), SB(OV6650, 101)}, #if !defined CONFIG_USB_SN9C102 && !defined CONFIG_USB_SN9C102_MODULE - {USB_DEVICE(0x0c45, 0x6019), /* SN9C101 */ - SFCI(OV7630, F_GAIN, 0, 0x21)}, - {USB_DEVICE(0x0c45, 0x6024), /* SN9C102 */ - SFCI(TAS5130CXX, 0, NO_EXPO|NO_FREQ, 0)}, - {USB_DEVICE(0x0c45, 0x6025), /* SN9C102 */ - SFCI(TAS5130CXX, 0, NO_EXPO|NO_FREQ, 0)}, - {USB_DEVICE(0x0c45, 0x6028), /* SN9C102 */ - SFCI(PAS202, 0, NO_EXPO|NO_FREQ, 0)}, - {USB_DEVICE(0x0c45, 0x6029), /* SN9C101 */ - SFCI(PAS106, F_SIF, NO_EXPO|NO_FREQ, 0)}, - {USB_DEVICE(0x0c45, 0x602c), /* SN9C102 */ - SFCI(OV7630, F_GAIN, 0, 0x21)}, + {USB_DEVICE(0x0c45, 0x6019), SB(OV7630, 101)}, + {USB_DEVICE(0x0c45, 0x6024), SB(TAS5130CXX, 102)}, + {USB_DEVICE(0x0c45, 0x6025), SB(TAS5130CXX, 102)}, + {USB_DEVICE(0x0c45, 0x6028), SB(PAS202, 102)}, + {USB_DEVICE(0x0c45, 0x6029), SB(PAS106, 102)}, + {USB_DEVICE(0x0c45, 0x602c), SB(OV7630, 102)}, #endif - {USB_DEVICE(0x0c45, 0x602d), /* SN9C102 */ - SFCI(HV7131R, 0, NO_EXPO|NO_FREQ, 0)}, + {USB_DEVICE(0x0c45, 0x602d), SB(HV7131R, 102)}, #if !defined CONFIG_USB_SN9C102 && !defined CONFIG_USB_SN9C102_MODULE - {USB_DEVICE(0x0c45, 0x602e), /* SN9C102 */ - SFCI(OV7630, F_GAIN, 0, 0x21)}, - {USB_DEVICE(0x0c45, 0x608f), /* SN9C103 */ - SFCI(OV7630, F_GAIN|F_H18, 0, 0x21)}, - {USB_DEVICE(0x0c45, 0x60af), /* SN9C103 */ - SFCI(PAS202, F_H18, NO_EXPO|NO_FREQ, 0)}, - {USB_DEVICE(0x0c45, 0x60b0), /* SN9C103 */ - SFCI(OV7630, F_GAIN|F_H18, 0, 0x21)}, + {USB_DEVICE(0x0c45, 0x602e), SB(OV7630, 102)}, + {USB_DEVICE(0x0c45, 0x608f), SB(OV7630, 103)}, + {USB_DEVICE(0x0c45, 0x60af), SB(PAS202, 103)}, + {USB_DEVICE(0x0c45, 0x60b0), SB(OV7630, 103)}, #endif {} }; -- cgit v0.10.2 From 5c51518da2cabc08af535cf041c6a3697f9e931f Mon Sep 17 00:00:00 2001 From: Hans de Goede Date: Wed, 3 Sep 2008 17:12:22 -0300 Subject: V4L/DVB (8834): gspca: Have a bigger buffer for sn9c10x compressed images. Under certain conditions sonixb compressed frame size can get bigger then the uncompressed size (seen with 0c45:6028), so make the buffers slightly bigger. Signed-off-by: Hans de Goede Signed-off-by: Jean-Francois Moine Signed-off-by: Mauro Carvalho Chehab diff --git a/drivers/media/video/gspca/sonixb.c b/drivers/media/video/gspca/sonixb.c index 8eaeaa3..346305b 100644 --- a/drivers/media/video/gspca/sonixb.c +++ b/drivers/media/video/gspca/sonixb.c @@ -207,29 +207,29 @@ static struct ctrl sd_ctrls[] = { static struct v4l2_pix_format vga_mode[] = { {160, 120, V4L2_PIX_FMT_SN9C10X, V4L2_FIELD_NONE, .bytesperline = 160, - .sizeimage = 160 * 120, + .sizeimage = 160 * 120 * 5 / 4, .colorspace = V4L2_COLORSPACE_SRGB, .priv = 2}, {320, 240, V4L2_PIX_FMT_SN9C10X, V4L2_FIELD_NONE, .bytesperline = 320, - .sizeimage = 320 * 240, + .sizeimage = 320 * 240 * 5 / 4, .colorspace = V4L2_COLORSPACE_SRGB, .priv = 1}, {640, 480, V4L2_PIX_FMT_SN9C10X, V4L2_FIELD_NONE, .bytesperline = 640, - .sizeimage = 640 * 480, + .sizeimage = 640 * 480 * 5 / 4, .colorspace = V4L2_COLORSPACE_SRGB, .priv = 0}, }; static struct v4l2_pix_format sif_mode[] = { {176, 144, V4L2_PIX_FMT_SN9C10X, V4L2_FIELD_NONE, .bytesperline = 176, - .sizeimage = 176 * 144, + .sizeimage = 176 * 144 * 5 / 4, .colorspace = V4L2_COLORSPACE_SRGB, .priv = 1}, {352, 288, V4L2_PIX_FMT_SN9C10X, V4L2_FIELD_NONE, .bytesperline = 352, - .sizeimage = 352 * 288, + .sizeimage = 352 * 288 * 5 / 4, .colorspace = V4L2_COLORSPACE_SRGB, .priv = 0}, }; -- cgit v0.10.2 From c437d657c59921b048997d5bc1f5733670112902 Mon Sep 17 00:00:00 2001 From: Hans de Goede Date: Wed, 3 Sep 2008 17:12:22 -0300 Subject: V4L/DVB (8835): gspca: Same pixfmt as the sn9c102 driver and raw Bayer added in sonixb. 1) Lower the hstart setting for all sensor by 1 so that we generate (compressed) BGGR data just like sn9c102 does (instead of GBRG data) 2) Add support for raw bayer output in the lowest resolutions (not enough bandwidth for higher resolutions), this should work with all sensors but to be sure only enable it for sensors where it has been tested. Signed-off-by: Hans de Goede Signed-off-by: Jean-Francois Moine Signed-off-by: Mauro Carvalho Chehab diff --git a/drivers/media/video/gspca/sonixb.c b/drivers/media/video/gspca/sonixb.c index 346305b..5033810 100644 --- a/drivers/media/video/gspca/sonixb.c +++ b/drivers/media/video/gspca/sonixb.c @@ -74,6 +74,10 @@ struct sensor_data { /* sensor_data flags */ #define F_GAIN 0x01 /* has gain */ #define F_SIF 0x02 /* sif or vga */ +#define F_RAW 0x04 /* sensor tested ok with raw bayer mode */ + +/* priv field of struct v4l2_pix_format flags (do not use low nibble!) */ +#define MODE_RAW 0x10 /* raw bayer mode */ /* ctrl_dis helper macros */ #define NO_EXPO ((1 << EXPOSURE_IDX) | (1 << AUTOGAIN_IDX)) @@ -205,6 +209,11 @@ static struct ctrl sd_ctrls[] = { }; static struct v4l2_pix_format vga_mode[] = { + {160, 120, V4L2_PIX_FMT_SBGGR8, V4L2_FIELD_NONE, + .bytesperline = 160, + .sizeimage = 160 * 120, + .colorspace = V4L2_COLORSPACE_SRGB, + .priv = 2 | MODE_RAW}, {160, 120, V4L2_PIX_FMT_SN9C10X, V4L2_FIELD_NONE, .bytesperline = 160, .sizeimage = 160 * 120 * 5 / 4, @@ -222,6 +231,11 @@ static struct v4l2_pix_format vga_mode[] = { .priv = 0}, }; static struct v4l2_pix_format sif_mode[] = { + {176, 144, V4L2_PIX_FMT_SBGGR8, V4L2_FIELD_NONE, + .bytesperline = 176, + .sizeimage = 176 * 144, + .colorspace = V4L2_COLORSPACE_SRGB, + .priv = 1 | MODE_RAW}, {176, 144, V4L2_PIX_FMT_SN9C10X, V4L2_FIELD_NONE, .bytesperline = 176, .sizeimage = 176 * 144 * 5 / 4, @@ -237,7 +251,7 @@ static struct v4l2_pix_format sif_mode[] = { static const __u8 initHv7131[] = { 0x46, 0x77, 0x00, 0x04, 0x00, 0x00, 0x00, 0x80, 0x11, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x03, 0x01, 0x00, /* shift from 0x02 0x01 0x00 */ + 0x00, 0x00, 0x00, 0x02, 0x01, 0x00, 0x28, 0x1e, 0x60, 0x8a, 0x20, 0x1d, 0x10, 0x02, 0x03, 0x0f, 0x0c }; @@ -251,7 +265,7 @@ static const __u8 hv7131_sensor_init[][8] = { static const __u8 initOv6650[] = { 0x44, 0x44, 0x00, 0x00, 0x00, 0x00, 0x00, 0x80, 0x60, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x02, 0x01, 0x0a, 0x16, 0x12, 0x68, 0x8b, + 0x00, 0x01, 0x01, 0x0a, 0x16, 0x12, 0x68, 0x8b, 0x10, 0x1d, 0x10, 0x00, 0x06, 0x1f, 0x00 }; static const __u8 ov6650_sensor_init[][8] = @@ -290,7 +304,7 @@ static const __u8 ov6650_sensor_init[][8] = static const __u8 initOv7630[] = { 0x04, 0x44, 0x00, 0x00, 0x00, 0x00, 0x00, 0x80, /* r01 .. r08 */ 0x21, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* r09 .. r10 */ - 0x00, 0x02, 0x01, 0x0a, /* r11 .. r14 */ + 0x00, 0x01, 0x01, 0x0a, /* r11 .. r14 */ 0x28, 0x1e, /* H & V sizes r15 .. r16 */ 0x68, COMP2, MCK_INIT1, /* r17 .. r19 */ 0x1d, 0x10, 0x02, 0x03, 0x0f, 0x0c /* r1a .. r1f */ @@ -334,7 +348,7 @@ static const __u8 ov7630_sensor_init_3[][8] = { static const __u8 initPas106[] = { 0x04, 0x03, 0x00, 0x00, 0x00, 0x00, 0x00, 0x81, 0x40, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x05, 0x01, 0x00, + 0x00, 0x00, 0x00, 0x04, 0x01, 0x00, 0x16, 0x12, 0x24, COMP1, MCK_INIT1, 0x18, 0x10, 0x04, 0x03, 0x11, 0x0c }; @@ -384,7 +398,7 @@ static const __u8 pas106_sensor_init[][8] = { static const __u8 initPas202[] = { 0x44, 0x44, 0x21, 0x30, 0x00, 0x00, 0x00, 0x80, 0x40, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x07, 0x03, 0x0a, /* 6 */ + 0x00, 0x00, 0x00, 0x06, 0x03, 0x0a, 0x28, 0x1e, 0x28, 0x89, 0x20, 0x00, 0x00, 0x02, 0x03, 0x0f, 0x0c }; @@ -415,7 +429,7 @@ static const __u8 pas202_sensor_init[][8] = { static const __u8 initTas5110[] = { 0x44, 0x03, 0x00, 0x00, 0x00, 0x00, 0x00, 0x20, 0x11, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x01, 0x00, 0x46, 0x09, 0x0a, /* shift from 0x45 0x09 0x0a */ + 0x00, 0x01, 0x00, 0x45, 0x09, 0x0a, 0x16, 0x12, 0x60, 0x86, 0x2b, 0x14, 0x0a, 0x02, 0x02, 0x09, 0x07 }; @@ -428,7 +442,7 @@ static const __u8 tas5110_sensor_init[][8] = { static const __u8 initTas5130[] = { 0x04, 0x03, 0x00, 0x00, 0x00, 0x00, 0x00, 0x20, 0x11, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x01, 0x00, 0x69, 0x0c, 0x0a, + 0x00, 0x01, 0x00, 0x68, 0x0c, 0x0a, 0x28, 0x1e, 0x60, COMP, MCK_INIT, 0x18, 0x10, 0x04, 0x03, 0x11, 0x0c }; @@ -442,14 +456,15 @@ static const __u8 tas5130_sensor_init[][8] = { struct sensor_data sensor_data[] = { SENS(initHv7131, NULL, hv7131_sensor_init, NULL, NULL, 0, NO_EXPO|NO_FREQ, 0), -SENS(initOv6650, NULL, ov6650_sensor_init, NULL, NULL, F_GAIN|F_SIF, 0, 0x60), +SENS(initOv6650, NULL, ov6650_sensor_init, NULL, NULL, F_GAIN|F_SIF|F_RAW, 0, + 0x60), SENS(initOv7630, initOv7630_3, ov7630_sensor_init, NULL, ov7630_sensor_init_3, F_GAIN, 0, 0x21), SENS(initPas106, NULL, pas106_sensor_init, NULL, NULL, F_SIF, NO_EXPO|NO_FREQ, 0), -SENS(initPas202, initPas202, pas202_sensor_init, NULL, NULL, 0, +SENS(initPas202, initPas202, pas202_sensor_init, NULL, NULL, F_RAW, NO_EXPO|NO_FREQ, 0), -SENS(initTas5110, NULL, tas5110_sensor_init, NULL, NULL, F_GAIN|F_SIF, +SENS(initTas5110, NULL, tas5110_sensor_init, NULL, NULL, F_GAIN|F_SIF|F_RAW, NO_BRIGHTNESS|NO_FREQ, 0), SENS(initTas5130, NULL, tas5130_sensor_init, NULL, NULL, 0, NO_EXPO|NO_FREQ, 0), @@ -819,6 +834,10 @@ static int sd_config(struct gspca_dev *gspca_dev, cam->cam_mode = sif_mode; cam->nmodes = ARRAY_SIZE(sif_mode); } + if (!(sensor_data[sd->sensor].flags & F_RAW)) { + cam->cam_mode++; + cam->nmodes--; + } sd->brightness = BRIGHTNESS_DEF; sd->gain = GAIN_DEF; sd->exposure = EXPOSURE_DEF; @@ -867,6 +886,9 @@ static void sd_start(struct gspca_dev *gspca_dev) reg17_19[2] = mode ? 0x23 : 0x43; break; } + /* Disable compression when the raw bayer format has been selected */ + if (gspca_dev->cam.cam_mode[gspca_dev->curr_mode].priv & MODE_RAW) + reg17_19[1] &= ~0x80; /* reg 0x01 bit 2 video transfert on */ reg_w(gspca_dev, 0x01, &sn9c10x[0x01 - 1], 1); @@ -929,6 +951,7 @@ static void sd_pkt_scan(struct gspca_dev *gspca_dev, { int i; struct sd *sd = (struct sd *) gspca_dev; + struct cam *cam = &gspca_dev->cam; /* frames start with: * ff ff 00 c4 c4 96 synchro @@ -982,6 +1005,17 @@ static void sd_pkt_scan(struct gspca_dev *gspca_dev, } } } + + if (cam->cam_mode[gspca_dev->curr_mode].priv & MODE_RAW) { + /* In raw mode we sometimes get some garbage after the frame + ignore this */ + int used = frame->data_end - frame->data; + int size = cam->cam_mode[gspca_dev->curr_mode].sizeimage; + + if (used + len > size) + len = size - used; + } + gspca_frame_add(gspca_dev, INTER_PACKET, frame, data, len); } -- cgit v0.10.2 From 1d434012f23effdc69d58a88229159b57256f6ba Mon Sep 17 00:00:00 2001 From: Jean Delvare Date: Wed, 3 Sep 2008 17:12:23 -0300 Subject: V4L/DVB (8837): dvb: fix I2C adapters name size Some DVB drivers are incorrectly assuming that the size of i2c_adapter.name is I2C_NAME_SIZE. Here's a fix. Also change strncpy to strlcpy, as the former is error-prone (and was indeed incorrectly used.) Signed-off-by: Jean Delvare Acked-by: Uwe Bugla Reviewed-by: Michael Krufky Signed-off-by: Steven Toth Signed-off-by: Andrew Morton Signed-off-by: Mauro Carvalho Chehab diff --git a/drivers/media/dvb/b2c2/flexcop-i2c.c b/drivers/media/dvb/b2c2/flexcop-i2c.c index 55973ea..43a112e 100644 --- a/drivers/media/dvb/b2c2/flexcop-i2c.c +++ b/drivers/media/dvb/b2c2/flexcop-i2c.c @@ -221,12 +221,12 @@ int flexcop_i2c_init(struct flexcop_device *fc) fc->fc_i2c_adap[1].port = FC_I2C_PORT_EEPROM; fc->fc_i2c_adap[2].port = FC_I2C_PORT_TUNER; - strncpy(fc->fc_i2c_adap[0].i2c_adap.name, - "B2C2 FlexCop I2C to demod", I2C_NAME_SIZE); - strncpy(fc->fc_i2c_adap[1].i2c_adap.name, - "B2C2 FlexCop I2C to eeprom", I2C_NAME_SIZE); - strncpy(fc->fc_i2c_adap[2].i2c_adap.name, - "B2C2 FlexCop I2C to tuner", I2C_NAME_SIZE); + strlcpy(fc->fc_i2c_adap[0].i2c_adap.name, "B2C2 FlexCop I2C to demod", + sizeof(fc->fc_i2c_adap[0].i2c_adap.name)); + strlcpy(fc->fc_i2c_adap[1].i2c_adap.name, "B2C2 FlexCop I2C to eeprom", + sizeof(fc->fc_i2c_adap[1].i2c_adap.name)); + strlcpy(fc->fc_i2c_adap[2].i2c_adap.name, "B2C2 FlexCop I2C to tuner", + sizeof(fc->fc_i2c_adap[2].i2c_adap.name)); i2c_set_adapdata(&fc->fc_i2c_adap[0].i2c_adap, &fc->fc_i2c_adap[0]); i2c_set_adapdata(&fc->fc_i2c_adap[1].i2c_adap, &fc->fc_i2c_adap[1]); diff --git a/drivers/media/dvb/frontends/cx24123.c b/drivers/media/dvb/frontends/cx24123.c index 386bd74..7156157 100644 --- a/drivers/media/dvb/frontends/cx24123.c +++ b/drivers/media/dvb/frontends/cx24123.c @@ -1072,8 +1072,8 @@ struct dvb_frontend* cx24123_attach(const struct cx24123_config* config, if (config->dont_use_pll) cx24123_repeater_mode(state, 1, 0); - strncpy(state->tuner_i2c_adapter.name, - "CX24123 tuner I2C bus", I2C_NAME_SIZE); + strlcpy(state->tuner_i2c_adapter.name, "CX24123 tuner I2C bus", + sizeof(state->tuner_i2c_adapter.name)); state->tuner_i2c_adapter.class = I2C_CLASS_TV_DIGITAL, state->tuner_i2c_adapter.algo = &cx24123_tuner_i2c_algo; state->tuner_i2c_adapter.algo_data = NULL; diff --git a/drivers/media/dvb/frontends/s5h1420.c b/drivers/media/dvb/frontends/s5h1420.c index 720ed9f..747d3fa 100644 --- a/drivers/media/dvb/frontends/s5h1420.c +++ b/drivers/media/dvb/frontends/s5h1420.c @@ -915,7 +915,8 @@ struct dvb_frontend *s5h1420_attach(const struct s5h1420_config *config, state->frontend.demodulator_priv = state; /* create tuner i2c adapter */ - strncpy(state->tuner_i2c_adapter.name, "S5H1420-PN1010 tuner I2C bus", I2C_NAME_SIZE); + strlcpy(state->tuner_i2c_adapter.name, "S5H1420-PN1010 tuner I2C bus", + sizeof(state->tuner_i2c_adapter.name)); state->tuner_i2c_adapter.class = I2C_CLASS_TV_DIGITAL, state->tuner_i2c_adapter.algo = &s5h1420_tuner_i2c_algo; state->tuner_i2c_adapter.algo_data = NULL; -- cgit v0.10.2 From af2a887c9aaca82306e9744d914ac335051ce987 Mon Sep 17 00:00:00 2001 From: Michael Krufky Date: Wed, 3 Sep 2008 17:12:24 -0300 Subject: V4L/DVB (8839): dib0700: add comment to identify 35th USB id pair This comment helps to make the code more readable. Signed-off-by: Michael Krufky Signed-off-by: Mauro Carvalho Chehab diff --git a/drivers/media/dvb/dvb-usb/dib0700_devices.c b/drivers/media/dvb/dvb-usb/dib0700_devices.c index 3dd20bf..e182aa1 100644 --- a/drivers/media/dvb/dvb-usb/dib0700_devices.c +++ b/drivers/media/dvb/dvb-usb/dib0700_devices.c @@ -1117,7 +1117,7 @@ struct usb_device_id dib0700_usb_id_table[] = { { USB_DEVICE(USB_VID_TERRATEC, USB_PID_TERRATEC_CINERGY_HT_EXPRESS) }, { USB_DEVICE(USB_VID_TERRATEC, USB_PID_TERRATEC_CINERGY_T_XXS) }, { USB_DEVICE(USB_VID_LEADTEK, USB_PID_WINFAST_DTV_DONGLE_STK7700P_2) }, - { USB_DEVICE(USB_VID_HAUPPAUGE, USB_PID_HAUPPAUGE_NOVA_TD_STICK_52009) }, +/* 35 */{ USB_DEVICE(USB_VID_HAUPPAUGE, USB_PID_HAUPPAUGE_NOVA_TD_STICK_52009) }, { 0 } /* Terminating entry */ }; MODULE_DEVICE_TABLE(usb, dib0700_usb_id_table); -- cgit v0.10.2 From 9a0c04a1ee3b4df6a30ae6975e13c558908df400 Mon Sep 17 00:00:00 2001 From: Michael Krufky Date: Wed, 3 Sep 2008 17:12:24 -0300 Subject: V4L/DVB (8840): dib0700: add basic support for Hauppauge Nova-TD-500 (84xxx) This adds basic support for the Hauppauge Nova-TD-500 84xxx series. A future patch will allow for one aerial input to supply both tuners. With the current code, an aerial must be plugged into each antannae input in order for both tuners to function. Signed-off-by: Michael Krufky Signed-off-by: Mauro Carvalho Chehab diff --git a/drivers/media/dvb/dvb-usb/dib0700_devices.c b/drivers/media/dvb/dvb-usb/dib0700_devices.c index e182aa1..6c0e5c5 100644 --- a/drivers/media/dvb/dvb-usb/dib0700_devices.c +++ b/drivers/media/dvb/dvb-usb/dib0700_devices.c @@ -1118,6 +1118,7 @@ struct usb_device_id dib0700_usb_id_table[] = { { USB_DEVICE(USB_VID_TERRATEC, USB_PID_TERRATEC_CINERGY_T_XXS) }, { USB_DEVICE(USB_VID_LEADTEK, USB_PID_WINFAST_DTV_DONGLE_STK7700P_2) }, /* 35 */{ USB_DEVICE(USB_VID_HAUPPAUGE, USB_PID_HAUPPAUGE_NOVA_TD_STICK_52009) }, + { USB_DEVICE(USB_VID_HAUPPAUGE, USB_PID_HAUPPAUGE_NOVA_T_500_3) }, { 0 } /* Terminating entry */ }; MODULE_DEVICE_TABLE(usb, dib0700_usb_id_table); @@ -1373,7 +1374,7 @@ struct dvb_usb_device_properties dib0700_devices[] = { } }, - .num_device_descs = 3, + .num_device_descs = 4, .devices = { { "DiBcom STK7070PD reference design", { &dib0700_usb_id_table[17], NULL }, @@ -1386,6 +1387,10 @@ struct dvb_usb_device_properties dib0700_devices[] = { { "Hauppauge Nova-TD Stick (52009)", { &dib0700_usb_id_table[35], NULL }, { NULL }, + }, + { "Hauppauge Nova-TD-500 (84xxx)", + { &dib0700_usb_id_table[36], NULL }, + { NULL }, } } }, { DIB0700_DEFAULT_DEVICE_PROPERTIES, diff --git a/drivers/media/dvb/dvb-usb/dvb-usb-ids.h b/drivers/media/dvb/dvb-usb/dvb-usb-ids.h index 029b437..03dfb9f 100644 --- a/drivers/media/dvb/dvb-usb/dvb-usb-ids.h +++ b/drivers/media/dvb/dvb-usb/dvb-usb-ids.h @@ -129,6 +129,7 @@ #define USB_PID_WINTV_NOVA_T_USB2_WARM 0x9301 #define USB_PID_HAUPPAUGE_NOVA_T_500 0x9941 #define USB_PID_HAUPPAUGE_NOVA_T_500_2 0x9950 +#define USB_PID_HAUPPAUGE_NOVA_T_500_3 0x8400 #define USB_PID_HAUPPAUGE_NOVA_T_STICK 0x7050 #define USB_PID_HAUPPAUGE_NOVA_T_STICK_2 0x7060 #define USB_PID_HAUPPAUGE_NOVA_T_STICK_3 0x7070 -- cgit v0.10.2 From 8da9bae3292ea8aee803e7cda295877c361f0694 Mon Sep 17 00:00:00 2001 From: Adrian Bunk Date: Wed, 3 Sep 2008 17:12:25 -0300 Subject: V4L/DVB (8842): vivi_release(): fix use-after-free video_device_release() does kfree(), which made the following printk() doing a use-after-free. printk() first and release then. Reported-by: Adrian Bunk Signed-off-by: Adrian Bunk Signed-off-by: Mauro Carvalho Chehab diff --git a/drivers/media/video/vivi.c b/drivers/media/video/vivi.c index f55d77d..8ba8daa 100644 --- a/drivers/media/video/vivi.c +++ b/drivers/media/video/vivi.c @@ -1021,13 +1021,13 @@ static int vivi_release(void) dev = list_entry(list, struct vivi_dev, vivi_devlist); if (-1 != dev->vfd->minor) { - video_unregister_device(dev->vfd); - printk(KERN_INFO "%s: /dev/video%d unregistered.\n", + printk(KERN_INFO "%s: unregistering /dev/video%d\n", VIVI_MODULE_NAME, dev->vfd->minor); + video_unregister_device(dev->vfd); } else { - video_device_release(dev->vfd); - printk(KERN_INFO "%s: /dev/video%d released.\n", + printk(KERN_INFO "%s: releasing /dev/video%d\n", VIVI_MODULE_NAME, dev->vfd->minor); + video_device_release(dev->vfd); } kfree(dev); -- cgit v0.10.2 From 877b5f4eda501ece641adbbea5d1940cbbfd4f38 Mon Sep 17 00:00:00 2001 From: Adrian Bunk Date: Wed, 3 Sep 2008 17:12:25 -0300 Subject: V4L/DVB (8843): tda10048_firmware_upload(): fix a memory leak This patch fixes a memory leak ("fw" wasn't freed). Reported-by: Adrian Bunk Signed-off-by: Adrian Bunk Signed-off-by: Mauro Carvalho Chehab diff --git a/drivers/media/dvb/frontends/tda10048.c b/drivers/media/dvb/frontends/tda10048.c index 7727099..04e7f1c 100644 --- a/drivers/media/dvb/frontends/tda10048.c +++ b/drivers/media/dvb/frontends/tda10048.c @@ -303,7 +303,7 @@ static int tda10048_firmware_upload(struct dvb_frontend *fe) if (fw->size != TDA10048_DEFAULT_FIRMWARE_SIZE) { printk(KERN_ERR "%s: firmware incorrect size\n", __func__); - return -EIO; + ret = -EIO; } else { printk(KERN_INFO "%s: firmware uploading\n", __func__); -- cgit v0.10.2 From 5d8538c1c6d85a7979c955b34f0e66d03be43da4 Mon Sep 17 00:00:00 2001 From: Adrian Bunk Date: Wed, 3 Sep 2008 17:12:25 -0300 Subject: V4L/DVB (8844): dabusb_fpga_download(): fix a memory leak This patch fixes a memory leak in an error path. Reported-by: Adrian Bunk Signed-off-by: Adrian Bunk Signed-off-by: Mauro Carvalho Chehab diff --git a/drivers/media/video/dabusb.c b/drivers/media/video/dabusb.c index 48f4b92..79faedf5 100644 --- a/drivers/media/video/dabusb.c +++ b/drivers/media/video/dabusb.c @@ -403,6 +403,7 @@ static int dabusb_fpga_download (pdabusb_t s, const char *fname) ret = request_firmware(&fw, "dabusb/bitstream.bin", &s->usbdev->dev); if (ret) { err("Failed to load \"dabusb/bitstream.bin\": %d\n", ret); + kfree(b); return ret; } -- cgit v0.10.2 From e6a5652fd156a286faadbf7a4062b5354d4e346e Mon Sep 17 00:00:00 2001 From: Chuck Ebbert Date: Wed, 3 Sep 2008 19:33:14 -0400 Subject: x86: add io delay quirk for Presario F700 Manually adding "io_delay=0xed" fixes system lockups in ioapic mode on this machine. System Information Manufacturer: Hewlett-Packard Product Name: Presario F700 (KA695EA#ABF) Base Board Information Manufacturer: Quanta Product Name: 30D3 Reference: https://bugzilla.redhat.com/show_bug.cgi?id=459546 Signed-off-by: Chuck Ebbert Signed-off-by: H. Peter Anvin diff --git a/arch/x86/kernel/io_delay.c b/arch/x86/kernel/io_delay.c index 1c3a66a..720d260 100644 --- a/arch/x86/kernel/io_delay.c +++ b/arch/x86/kernel/io_delay.c @@ -92,6 +92,14 @@ static struct dmi_system_id __initdata io_delay_0xed_port_dmi_table[] = { DMI_MATCH(DMI_BOARD_NAME, "30BF") } }, + { + .callback = dmi_io_delay_0xed_port, + .ident = "Presario F700", + .matches = { + DMI_MATCH(DMI_BOARD_VENDOR, "Quanta"), + DMI_MATCH(DMI_BOARD_NAME, "30D3") + } + }, { } }; -- cgit v0.10.2 From ce36394269ccd9d1d286d6192ba09fa6894365e9 Mon Sep 17 00:00:00 2001 From: Tejun Heo Date: Wed, 3 Sep 2008 16:09:47 +0200 Subject: mmap: fix petty bug in anonymous shared mmap offset handling Anonymous mappings should ignore offset but shared anonymous mapping forgot to clear it and makes the following legit test program trigger SIGBUS. #include #include #include #define PAGE_SIZE 4096 int main(void) { char *p; int i; p = mmap(NULL, 2 * PAGE_SIZE, PROT_READ|PROT_WRITE, MAP_SHARED|MAP_ANONYMOUS, -1, PAGE_SIZE); if (p == MAP_FAILED) { perror("mmap"); return 1; } for (i = 0; i < 2; i++) { printf("page %d\n", i); p[i * 4096] = i; } return 0; } Fix it. Signed-off-by: Tejun Heo Acked-by: Hugh Dickins Acked-by: KOSAKI Motohiro Signed-off-by: Linus Torvalds diff --git a/mm/mmap.c b/mm/mmap.c index 339cf5c..e7a5a68 100644 --- a/mm/mmap.c +++ b/mm/mmap.c @@ -1030,6 +1030,10 @@ unsigned long do_mmap_pgoff(struct file * file, unsigned long addr, } else { switch (flags & MAP_TYPE) { case MAP_SHARED: + /* + * Ignore pgoff. + */ + pgoff = 0; vm_flags |= VM_SHARED | VM_MAYSHARE; break; case MAP_PRIVATE: -- cgit v0.10.2 From de014d617636d6a6bd5aef3b3d1f7f9a35669057 Mon Sep 17 00:00:00 2001 From: Alok N Kataria Date: Wed, 3 Sep 2008 18:18:01 -0700 Subject: x86: Change warning message in TSC calibration. When calibration against PIT fails, the warning that we print is misleading. In a virtualized environment the VM may get descheduled while calibration or, the check in PIT calibration may fail due to other virtualization overheads. The warning message explicitly assumes that calibration failed due to SMI's which may not be the case. Change that to something proper. Signed-off-by: Alok N Kataria Signed-off-by: Linus Torvalds diff --git a/arch/x86/kernel/tsc.c b/arch/x86/kernel/tsc.c index 346cae5..8f98e9d 100644 --- a/arch/x86/kernel/tsc.c +++ b/arch/x86/kernel/tsc.c @@ -267,8 +267,7 @@ unsigned long native_calibrate_tsc(void) */ if (tsc_pit_min == ULONG_MAX) { /* PIT gave no useful value */ - printk(KERN_WARNING "TSC: PIT calibration failed due to " - "SMI disturbance.\n"); + printk(KERN_WARNING "TSC: Unable to calibrate against PIT\n"); /* We don't have an alternative source, disable TSC */ if (!hpet && !pm1 && !pm2) { -- cgit v0.10.2 From 5f17cfce5776c566d64430f543a289e5cfa4538b Mon Sep 17 00:00:00 2001 From: Linus Torvalds Date: Thu, 4 Sep 2008 01:33:59 -0700 Subject: PCI: fix pbus_size_mem() resource alignment for CardBus controllers Commit 884525655d07fdee9245716b998ecdc45cdd8007 ("PCI: clean up resource alignment management") changed the resource handling to mark how a resource was aligned on a per-resource basis. Thus, instead of looking at the resource number to determine whether it was a bridge resource or a regular resource (they have different alignment rules), we should just ask the resource for its alignment directly. The reason this broke only cardbus resources was that for the other types of resources, the old way of deciding alignment actually still happened to work. But CardBus bridge resources had been changed by commit 934b7024f0ed29003c95cef447d92737ab86dc4f ("Fix cardbus resource allocation") to look more like regular resources than PCI bridge resources from an alignment handling standpoint. Reported-and-tested-by: Andrew Morton Cc: Ivan Kokshaysky Cc: Jesse Barnes Signed-off-by: Linus Torvalds diff --git a/drivers/pci/setup-bus.c b/drivers/pci/setup-bus.c index 82634a2..1aad599 100644 --- a/drivers/pci/setup-bus.c +++ b/drivers/pci/setup-bus.c @@ -352,11 +352,12 @@ static int pbus_size_mem(struct pci_bus *bus, unsigned long mask, unsigned long continue; r_size = r->end - r->start + 1; /* For bridges size != alignment */ - align = (i < PCI_BRIDGE_RESOURCES) ? r_size : r->start; + align = resource_alignment(r); order = __ffs(align) - 20; if (order > 11) { - dev_warn(&dev->dev, "BAR %d too large: " + dev_warn(&dev->dev, "BAR %d bad alignment %llx: " "%#016llx-%#016llx\n", i, + (unsigned long long)align, (unsigned long long)r->start, (unsigned long long)r->end); r->flags = 0; -- cgit v0.10.2 From c3df1a2685004bce97827bdbe7a304734009849b Mon Sep 17 00:00:00 2001 From: Russell King Date: Wed, 3 Sep 2008 23:59:23 +0100 Subject: [ARM] omap: fix build error in ohci-omap.c drivers/usb/host/ohci-omap.c: In function 'ohci_omap_init': drivers/usb/host/ohci-omap.c:228: error: 'start_hnp' undeclared (first use in this function) Signed-off-by: Russell King diff --git a/drivers/usb/host/ohci-omap.c b/drivers/usb/host/ohci-omap.c index 1eb64d0..95b3ec8 100644 --- a/drivers/usb/host/ohci-omap.c +++ b/drivers/usb/host/ohci-omap.c @@ -208,7 +208,7 @@ static int ohci_omap_init(struct usb_hcd *hcd) if (cpu_is_omap16xx()) ocpi_enable(); -#ifdef CONFIG_ARCH_OMAP_OTG +#ifdef CONFIG_USB_OTG if (need_transceiver) { ohci->transceiver = otg_get_transceiver(); if (ohci->transceiver) { -- cgit v0.10.2 From 8b540fdcb7c445d61955991f071e956ef40a2f17 Mon Sep 17 00:00:00 2001 From: Huang Weiyi Date: Sat, 23 Aug 2008 13:56:02 +0800 Subject: [ARM] remove unused #include The driver(s) below do not use LINUX_VERSION_CODE nor KERNEL_VERSION. arch/arm/plat-mxc/clock.c This patch removes the said #include . Signed-off-by: Huang Weiyi Signed-off-by: Russell King diff --git a/arch/arm/plat-mxc/clock.c b/arch/arm/plat-mxc/clock.c index 2f86272..0a38f0b 100644 --- a/arch/arm/plat-mxc/clock.c +++ b/arch/arm/plat-mxc/clock.c @@ -37,7 +37,6 @@ #include #include #include -#include #include -- cgit v0.10.2 From 54cd3148a149f7413cc25cb832f42cf0dabcee29 Mon Sep 17 00:00:00 2001 From: Andi Kleen Date: Thu, 4 Sep 2008 13:30:07 +0200 Subject: ACPI: Make Len Brown the ACPI maintainer again Len is back! Signed-off-by: Andi Kleen diff --git a/MAINTAINERS b/MAINTAINERS index 663485b..9fc7c1c 100644 --- a/MAINTAINERS +++ b/MAINTAINERS @@ -222,8 +222,7 @@ W: http://code.google.com/p/aceracpi S: Maintained ACPI -P: Andi Kleen -M: ak@linux.intel.com +P: Len Brown M: lenb@kernel.org L: linux-acpi@vger.kernel.org W: http://www.lesswatts.org/projects/acpi/ -- cgit v0.10.2 From d8196a93b1ce9a5abb410f39f9375912c9e53675 Mon Sep 17 00:00:00 2001 From: Jonathan Woithe Date: Fri, 29 Aug 2008 11:06:21 +0930 Subject: fujitsu-laptop: fix regression for P8010 in 2.6.27-rc The following patch (based on a patch from Stephen Gildea) fixes a regression with the LCD brightness keys on Fujitsu P8010 laptops which was observed with the 2.6.27-rc series (basically they stopped working due to changes within the fujitsu-laptop and video modules). Please apply to 2.6.27-rc and acpi git. A more complete solution for this laptop will be included in an upcoming patch, hopefully for 2.6.28. In the meantime this restores most functionality for P8010 users. Signed-off-by: Stephen Gildea Signed-off-by: Jonathan Woithe Signed-off-by: Andi Kleen diff --git a/drivers/misc/fujitsu-laptop.c b/drivers/misc/fujitsu-laptop.c index 7a1ef6c..3e56203 100644 --- a/drivers/misc/fujitsu-laptop.c +++ b/drivers/misc/fujitsu-laptop.c @@ -463,6 +463,13 @@ static struct dmi_system_id __initdata fujitsu_dmi_table[] = { DMI_MATCH(DMI_PRODUCT_NAME, "LIFEBOOK S6410"), }, .callback = dmi_check_cb_s6410}, + { + .ident = "FUJITSU LifeBook P8010", + .matches = { + DMI_MATCH(DMI_SYS_VENDOR, "FUJITSU"), + DMI_MATCH(DMI_PRODUCT_NAME, "LifeBook P8010"), + }, + .callback = dmi_check_cb_s6410}, {} }; -- cgit v0.10.2 From 266feefeb9ea2d846ac82eb6db1a54b230364ba4 Mon Sep 17 00:00:00 2001 From: Zhao Yakui Date: Tue, 26 Aug 2008 13:57:34 +0800 Subject: ACPI: Avoid bogus timeout about SMbus check MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit In the function of wait_transaction_complete when the timeout happens, OS will try to check the status of SMbus again. If the status is what OS expected, it will be regarded as the bogus timeout. Otherwise it will be treated as ETIME. http://bugzilla.kernel.org/show_bug.cgi?id=10483 Signed-off-by: Zhao Yakui tested-by : Oldřich Jedlička < Signed-off-by: Andi Kleen diff --git a/drivers/acpi/sbshc.c b/drivers/acpi/sbshc.c index bcf2c70..a4e3767 100644 --- a/drivers/acpi/sbshc.c +++ b/drivers/acpi/sbshc.c @@ -107,6 +107,13 @@ static int wait_transaction_complete(struct acpi_smb_hc *hc, int timeout) if (wait_event_timeout(hc->wait, smb_check_done(hc), msecs_to_jiffies(timeout))) return 0; + /* + * After the timeout happens, OS will try to check the status of SMbus. + * If the status is what OS expected, it will be regarded as the bogus + * timeout. + */ + if (smb_check_done(hc)) + return 0; else return -ETIME; } -- cgit v0.10.2 From 7d964c352b06aabb895e39d3b479e105bd9d1ca0 Mon Sep 17 00:00:00 2001 From: Russ Dill Date: Tue, 2 Sep 2008 14:35:40 -0700 Subject: acer-wmi: remove debugfs entries upon unloading The exit function neglects to remove debugfs entries, leading to a BUG on reload. [akpm@linux-foundation.org: cleanups] Signed-off-by: Russ Dill Acked-by: Carlos Corbacho Cc: Andi Kleen Signed-off-by: Andrew Morton Signed-off-by: Andi Kleen diff --git a/drivers/misc/acer-wmi.c b/drivers/misc/acer-wmi.c index e7a3fe5..9c883f8 100644 --- a/drivers/misc/acer-wmi.c +++ b/drivers/misc/acer-wmi.c @@ -1167,7 +1167,7 @@ static int create_debugfs(void) return 0; error_debugfs: - remove_debugfs(); + remove_debugfs(); return -ENOMEM; } @@ -1248,6 +1248,7 @@ error_platform_register: static void __exit acer_wmi_exit(void) { remove_sysfs(acer_platform_device); + remove_debugfs(); platform_device_del(acer_platform_device); platform_driver_unregister(&acer_platform_driver); -- cgit v0.10.2 From b380b0d4f7dffcc235c0facefa537d4655619101 Mon Sep 17 00:00:00 2001 From: Al Viro Date: Thu, 4 Sep 2008 17:05:57 +0100 Subject: forgotten refcount on sysctl root table We should've set refcount on the root sysctl table; otherwise we'll blow up the first time we get down to zero dynamically registered sysctl tables. Signed-off-by: Al Viro Tested-by: James Bottomley Signed-off-by: Linus Torvalds diff --git a/kernel/sysctl.c b/kernel/sysctl.c index fe47133..50ec088 100644 --- a/kernel/sysctl.c +++ b/kernel/sysctl.c @@ -159,6 +159,7 @@ static int proc_dointvec_taint(struct ctl_table *table, int write, struct file * static struct ctl_table root_table[]; static struct ctl_table_root sysctl_table_root; static struct ctl_table_header root_table_header = { + .count = 1, .ctl_table = root_table, .ctl_entry = LIST_HEAD_INIT(sysctl_table_root.default_set.list), .root = &sysctl_table_root, -- cgit v0.10.2 From 9362773624bcde3ccc198fefcf3c584e5058f645 Mon Sep 17 00:00:00 2001 From: Hans de Goede Date: Thu, 4 Sep 2008 16:20:12 -0300 Subject: V4L/DVB (8868): gspca: Support for vga modes with sif sensors in sonixb. - Add documentation for some known registers - Add support for vga modes (320x240, 160x120) for sif sensors - Remove F_RAW sensor flag raw mode should work on any sensor as its a bridge only thing and keeping the flag was becoming awkward. - Fixup ov6650 and pas106 auto exposure window settings Signed-off-by: Hans de Goede Signed-off-by: Jean-Francois Moine Signed-off-by: Mauro Carvalho Chehab diff --git a/drivers/media/video/gspca/sonixb.c b/drivers/media/video/gspca/sonixb.c index 5033810..7f67148 100644 --- a/drivers/media/video/gspca/sonixb.c +++ b/drivers/media/video/gspca/sonixb.c @@ -20,6 +20,26 @@ * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA */ +/* Some documentation on known sonixb registers: + +Reg Use +0x10 high nibble red gain low nibble blue gain +0x11 low nibble green gain +0x12 hstart +0x13 vstart +0x15 hsize (hsize = register-value * 16) +0x16 vsize (vsize = register-value * 16) +0x17 bit 0 toggle compression quality (according to sn9c102 driver) +0x18 bit 7 enables compression, bit 4-5 set image down scaling: + 00 scale 1, 01 scale 1/2, 10, scale 1/4 +0x19 high-nibble is sensor clock divider, changes exposure on sensors which + use a clock generated by the bridge. Some sensors have their own clock. +0x1c auto_exposure area (for avg_lum) startx (startx = register-value * 32) +0x1d auto_exposure area (for avg_lum) starty (starty = register-value * 32) +0x1e auto_exposure area (for avg_lum) stopx (hsize = (0x1e - 0x1c) * 32) +0x1f auto_exposure area (for avg_lum) stopy (vsize = (0x1f - 0x1d) * 32) +*/ + #define MODULE_NAME "sonixb" #include "gspca.h" @@ -74,10 +94,10 @@ struct sensor_data { /* sensor_data flags */ #define F_GAIN 0x01 /* has gain */ #define F_SIF 0x02 /* sif or vga */ -#define F_RAW 0x04 /* sensor tested ok with raw bayer mode */ /* priv field of struct v4l2_pix_format flags (do not use low nibble!) */ #define MODE_RAW 0x10 /* raw bayer mode */ +#define MODE_REDUCED_SIF 0x20 /* vga mode (320x240 / 160x120) on sif cam */ /* ctrl_dis helper macros */ #define NO_EXPO ((1 << EXPOSURE_IDX) | (1 << AUTOGAIN_IDX)) @@ -211,7 +231,7 @@ static struct ctrl sd_ctrls[] = { static struct v4l2_pix_format vga_mode[] = { {160, 120, V4L2_PIX_FMT_SBGGR8, V4L2_FIELD_NONE, .bytesperline = 160, - .sizeimage = 160 * 120, + .sizeimage = 160 * 120 * 5 / 4, .colorspace = V4L2_COLORSPACE_SRGB, .priv = 2 | MODE_RAW}, {160, 120, V4L2_PIX_FMT_SN9C10X, V4L2_FIELD_NONE, @@ -231,9 +251,19 @@ static struct v4l2_pix_format vga_mode[] = { .priv = 0}, }; static struct v4l2_pix_format sif_mode[] = { + {160, 120, V4L2_PIX_FMT_SBGGR8, V4L2_FIELD_NONE, + .bytesperline = 160, + .sizeimage = 160 * 120, + .colorspace = V4L2_COLORSPACE_SRGB, + .priv = 1 | MODE_RAW | MODE_REDUCED_SIF}, + {160, 120, V4L2_PIX_FMT_SN9C10X, V4L2_FIELD_NONE, + .bytesperline = 160, + .sizeimage = 160 * 120 * 5 / 4, + .colorspace = V4L2_COLORSPACE_SRGB, + .priv = 1 | MODE_REDUCED_SIF}, {176, 144, V4L2_PIX_FMT_SBGGR8, V4L2_FIELD_NONE, .bytesperline = 176, - .sizeimage = 176 * 144, + .sizeimage = 176 * 144 * 5 / 4, .colorspace = V4L2_COLORSPACE_SRGB, .priv = 1 | MODE_RAW}, {176, 144, V4L2_PIX_FMT_SN9C10X, V4L2_FIELD_NONE, @@ -241,6 +271,11 @@ static struct v4l2_pix_format sif_mode[] = { .sizeimage = 176 * 144 * 5 / 4, .colorspace = V4L2_COLORSPACE_SRGB, .priv = 1}, + {320, 240, V4L2_PIX_FMT_SN9C10X, V4L2_FIELD_NONE, + .bytesperline = 320, + .sizeimage = 320 * 240 * 5 / 4, + .colorspace = V4L2_COLORSPACE_SRGB, + .priv = 0 | MODE_REDUCED_SIF}, {352, 288, V4L2_PIX_FMT_SN9C10X, V4L2_FIELD_NONE, .bytesperline = 352, .sizeimage = 352 * 288 * 5 / 4, @@ -266,7 +301,7 @@ static const __u8 initOv6650[] = { 0x44, 0x44, 0x00, 0x00, 0x00, 0x00, 0x00, 0x80, 0x60, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x01, 0x01, 0x0a, 0x16, 0x12, 0x68, 0x8b, - 0x10, 0x1d, 0x10, 0x00, 0x06, 0x1f, 0x00 + 0x10, 0x1d, 0x10, 0x02, 0x02, 0x09, 0x07 }; static const __u8 ov6650_sensor_init[][8] = { @@ -350,7 +385,7 @@ static const __u8 initPas106[] = { 0x00, 0x00, 0x00, 0x00, 0x00, 0x04, 0x01, 0x00, 0x16, 0x12, 0x24, COMP1, MCK_INIT1, - 0x18, 0x10, 0x04, 0x03, 0x11, 0x0c + 0x18, 0x10, 0x02, 0x02, 0x09, 0x07 }; /* compression 0x86 mckinit1 0x2b */ static const __u8 pas106_sensor_init[][8] = { @@ -456,15 +491,14 @@ static const __u8 tas5130_sensor_init[][8] = { struct sensor_data sensor_data[] = { SENS(initHv7131, NULL, hv7131_sensor_init, NULL, NULL, 0, NO_EXPO|NO_FREQ, 0), -SENS(initOv6650, NULL, ov6650_sensor_init, NULL, NULL, F_GAIN|F_SIF|F_RAW, 0, - 0x60), +SENS(initOv6650, NULL, ov6650_sensor_init, NULL, NULL, F_GAIN|F_SIF, 0, 0x60), SENS(initOv7630, initOv7630_3, ov7630_sensor_init, NULL, ov7630_sensor_init_3, F_GAIN, 0, 0x21), SENS(initPas106, NULL, pas106_sensor_init, NULL, NULL, F_SIF, NO_EXPO|NO_FREQ, 0), -SENS(initPas202, initPas202, pas202_sensor_init, NULL, NULL, F_RAW, +SENS(initPas202, initPas202, pas202_sensor_init, NULL, NULL, 0, NO_EXPO|NO_FREQ, 0), -SENS(initTas5110, NULL, tas5110_sensor_init, NULL, NULL, F_GAIN|F_SIF|F_RAW, +SENS(initTas5110, NULL, tas5110_sensor_init, NULL, NULL, F_GAIN|F_SIF, NO_BRIGHTNESS|NO_FREQ, 0), SENS(initTas5130, NULL, tas5130_sensor_init, NULL, NULL, 0, NO_EXPO|NO_FREQ, 0), @@ -834,10 +868,6 @@ static int sd_config(struct gspca_dev *gspca_dev, cam->cam_mode = sif_mode; cam->nmodes = ARRAY_SIZE(sif_mode); } - if (!(sensor_data[sd->sensor].flags & F_RAW)) { - cam->cam_mode++; - cam->nmodes--; - } sd->brightness = BRIGHTNESS_DEF; sd->gain = GAIN_DEF; sd->exposure = EXPOSURE_DEF; @@ -864,31 +894,39 @@ static int sd_init(struct gspca_dev *gspca_dev) static void sd_start(struct gspca_dev *gspca_dev) { struct sd *sd = (struct sd *) gspca_dev; + struct cam *cam = &gspca_dev->cam; int mode, l; const __u8 *sn9c10x; - __u8 reg17_19[3]; + __u8 reg12_19[8]; - mode = gspca_dev->cam.cam_mode[(int) gspca_dev->curr_mode].priv & 0x07; + mode = cam->cam_mode[gspca_dev->curr_mode].priv & 0x07; sn9c10x = sensor_data[sd->sensor].bridge_init[sd->bridge]; l = sensor_data[sd->sensor].bridge_init_size[sd->bridge]; - reg17_19[0] = sn9c10x[0x17 - 1]; - reg17_19[1] = sn9c10x[0x18 - 1] | (mode << 4); - reg17_19[2] = sn9c10x[0x19 - 1]; + memcpy(reg12_19, &sn9c10x[0x12 - 1], 8); + reg12_19[6] = sn9c10x[0x18 - 1] | (mode << 4); /* Special cases where reg 17 and or 19 value depends on mode */ switch (sd->sensor) { case SENSOR_PAS202: - reg17_19[0] = mode ? 0x24 : 0x20; + reg12_19[5] = mode ? 0x24 : 0x20; break; case SENSOR_TAS5130CXX: /* probably not mode specific at all most likely the upper nibble of 0x19 is exposure (clock divider) just as with the tas5110, we need someone to test this. */ - reg17_19[2] = mode ? 0x23 : 0x43; + reg12_19[7] = mode ? 0x23 : 0x43; break; } /* Disable compression when the raw bayer format has been selected */ - if (gspca_dev->cam.cam_mode[gspca_dev->curr_mode].priv & MODE_RAW) - reg17_19[1] &= ~0x80; + if (cam->cam_mode[gspca_dev->curr_mode].priv & MODE_RAW) + reg12_19[6] &= ~0x80; + + /* Vga mode emulation on SIF sensor? */ + if (cam->cam_mode[gspca_dev->curr_mode].priv & MODE_REDUCED_SIF) { + reg12_19[0] += 16; /* 0x12: hstart adjust */ + reg12_19[1] += 24; /* 0x13: vstart adjust */ + reg12_19[3] = 320 / 16; /* 0x15: hsize */ + reg12_19[4] = 240 / 16; /* 0x16: vsize */ + } /* reg 0x01 bit 2 video transfert on */ reg_w(gspca_dev, 0x01, &sn9c10x[0x01 - 1], 1); @@ -907,24 +945,24 @@ static void sd_start(struct gspca_dev *gspca_dev) sd->bridge]); /* H_size V_size 0x28, 0x1e -> 640x480. 0x16, 0x12 -> 352x288 */ - reg_w(gspca_dev, 0x15, &sn9c10x[0x15 - 1], 2); + reg_w(gspca_dev, 0x15, ®12_19[3], 2); /* compression register */ - reg_w(gspca_dev, 0x18, ®17_19[1], 1); + reg_w(gspca_dev, 0x18, ®12_19[6], 1); /* H_start */ - reg_w(gspca_dev, 0x12, &sn9c10x[0x12 - 1], 1); + reg_w(gspca_dev, 0x12, ®12_19[0], 1); /* V_START */ - reg_w(gspca_dev, 0x13, &sn9c10x[0x13 - 1], 1); + reg_w(gspca_dev, 0x13, ®12_19[1], 1); /* reset 0x17 SensorClk enable inv Clk 0x60 */ /*fixme: ov7630 [17]=68 8f (+20 if 102)*/ - reg_w(gspca_dev, 0x17, ®17_19[0], 1); + reg_w(gspca_dev, 0x17, ®12_19[5], 1); /*MCKSIZE ->3 */ /*fixme: not ov7630*/ - reg_w(gspca_dev, 0x19, ®17_19[2], 1); + reg_w(gspca_dev, 0x19, ®12_19[7], 1); /* AE_STRX AE_STRY AE_ENDX AE_ENDY */ reg_w(gspca_dev, 0x1c, &sn9c10x[0x1c - 1], 4); /* Enable video transfert */ reg_w(gspca_dev, 0x01, &sn9c10x[0], 1); /* Compression */ - reg_w(gspca_dev, 0x18, ®17_19[1], 2); + reg_w(gspca_dev, 0x18, ®12_19[6], 2); msleep(20); sd->reg11 = -1; -- cgit v0.10.2 From a94a508691d16420ad10572a33db4d45115b5f75 Mon Sep 17 00:00:00 2001 From: Hans de Goede Date: Thu, 4 Sep 2008 16:22:55 -0300 Subject: V4L/DVB (8869): gspca: Move the Sonix webcams with TAS5110C1B from sn9c102 to gspca. This patch makes gspca claim the USB-ID for sn9c101/2 cams with a TAS5110C1B sensor even if both gspca and sn9c102 are enabled, as these cams are much better supported under gspca (and extensively tested with gspca). It also removes an usb-id from sn9c102 for one more unsupported bridge sensor combo. Signed-off-by: Hans de Goede Signed-off-by: Jean-Francois Moine Signed-off-by: Mauro Carvalho Chehab diff --git a/drivers/media/video/gspca/sonixb.c b/drivers/media/video/gspca/sonixb.c index 7f67148..bde9ea9 100644 --- a/drivers/media/video/gspca/sonixb.c +++ b/drivers/media/video/gspca/sonixb.c @@ -1201,10 +1201,10 @@ static const struct sd_desc sd_desc = { static __devinitdata struct usb_device_id device_table[] = { + {USB_DEVICE(0x0c45, 0x6001), SB(TAS5110, 102)}, /* TAS5110C1B */ + {USB_DEVICE(0x0c45, 0x6005), SB(TAS5110, 101)}, /* TAS5110C1B */ #if !defined CONFIG_USB_SN9C102 && !defined CONFIG_USB_SN9C102_MODULE - {USB_DEVICE(0x0c45, 0x6001), SB(TAS5110, 102)}, - {USB_DEVICE(0x0c45, 0x6005), SB(TAS5110, 101)}, - {USB_DEVICE(0x0c45, 0x6007), SB(TAS5110, 101)}, + {USB_DEVICE(0x0c45, 0x6007), SB(TAS5110, 101)}, /* TAS5110D */ {USB_DEVICE(0x0c45, 0x6009), SB(PAS106, 101)}, {USB_DEVICE(0x0c45, 0x600d), SB(PAS106, 101)}, #endif diff --git a/drivers/media/video/sn9c102/sn9c102_devtable.h b/drivers/media/video/sn9c102/sn9c102_devtable.h index 85499a3..f474914 100644 --- a/drivers/media/video/sn9c102/sn9c102_devtable.h +++ b/drivers/media/video/sn9c102/sn9c102_devtable.h @@ -40,8 +40,10 @@ struct sn9c102_device; static const struct usb_device_id sn9c102_id_table[] = { /* SN9C101 and SN9C102 */ +#if !defined CONFIG_USB_GSPCA && !defined CONFIG_USB_GSPCA_MODULE { SN9C102_USB_DEVICE(0x0c45, 0x6001, BRIDGE_SN9C102), }, { SN9C102_USB_DEVICE(0x0c45, 0x6005, BRIDGE_SN9C102), }, +#endif { SN9C102_USB_DEVICE(0x0c45, 0x6007, BRIDGE_SN9C102), }, { SN9C102_USB_DEVICE(0x0c45, 0x6009, BRIDGE_SN9C102), }, { SN9C102_USB_DEVICE(0x0c45, 0x600d, BRIDGE_SN9C102), }, @@ -72,7 +74,7 @@ static const struct usb_device_id sn9c102_id_table[] = { { SN9C102_USB_DEVICE(0x0c45, 0x60a3, BRIDGE_SN9C103), }, /* { SN9C102_USB_DEVICE(0x0c45, 0x60a8, BRIDGE_SN9C103), }, PAS106 */ /* { SN9C102_USB_DEVICE(0x0c45, 0x60aa, BRIDGE_SN9C103), }, TAS5130 */ - { SN9C102_USB_DEVICE(0x0c45, 0x60ab, BRIDGE_SN9C103), }, +/* { SN9C102_USB_DEVICE(0x0c45, 0x60ab, BRIDGE_SN9C103), }, TAS5130 */ { SN9C102_USB_DEVICE(0x0c45, 0x60ac, BRIDGE_SN9C103), }, { SN9C102_USB_DEVICE(0x0c45, 0x60ae, BRIDGE_SN9C103), }, { SN9C102_USB_DEVICE(0x0c45, 0x60af, BRIDGE_SN9C103), }, -- cgit v0.10.2 From bf2a2202f75cda679303f09d150f9549f9835953 Mon Sep 17 00:00:00 2001 From: Hans de Goede Date: Thu, 4 Sep 2008 16:22:56 -0300 Subject: V4L/DVB (8870): gspca: Fix dark room problem with sonixb. When using the sonixb driver in a dark room and given that the autoexposure algorithm starts with a setting most suitable for daylight, the picture produced by the cam may actually be 100% black leading to a avg_lum value of 0, so an avg_lum value of 0 does not always signal an exposure settings change (which it normally does). This patch adds a check for the really black image case and stops dropping all frames as invalid in this case. Signed-off-by: Hans de Goede Signed-off-by: Jean-Francois Moine Signed-off-by: Mauro Carvalho Chehab diff --git a/drivers/media/video/gspca/sonixb.c b/drivers/media/video/gspca/sonixb.c index bde9ea9..64bc758 100644 --- a/drivers/media/video/gspca/sonixb.c +++ b/drivers/media/video/gspca/sonixb.c @@ -52,6 +52,7 @@ MODULE_LICENSE("GPL"); struct sd { struct gspca_dev gspca_dev; /* !! must be the first item */ atomic_t avg_lum; + int prev_avg_lum; unsigned char gain; unsigned char exposure; @@ -1022,10 +1023,19 @@ static void sd_pkt_scan(struct gspca_dev *gspca_dev, } else { lum = data[i + 8] + (data[i + 9] << 8); } - if (lum == 0) { + /* When exposure changes midway a frame we + get a lum of 0 in this case drop 2 frames + as the frames directly after an exposure + change have an unstable image. Sometimes lum + *really* is 0 (cam used in low light with + low exposure setting), so do not drop frames + if the previous lum was 0 too. */ + if (lum == 0 && sd->prev_avg_lum != 0) { lum = -1; sd->frames_to_drop = 2; - } + sd->prev_avg_lum = 0; + } else + sd->prev_avg_lum = lum; atomic_set(&sd->avg_lum, lum); if (sd->frames_to_drop) { -- cgit v0.10.2 From b77c0046a63e7aa87152f9978cf7c46e7bead7fc Mon Sep 17 00:00:00 2001 From: Jean-Francois Moine Date: Thu, 4 Sep 2008 16:22:56 -0300 Subject: V4L/DVB (8872): gspca: Bad image format and offset with rev072a of spca561. - have 2 pixfmt tables - offset of Bayer frames at 16 instead of 20. Signed-off-by: Jean-Francois Moine Signed-off-by: Mauro Carvalho Chehab diff --git a/drivers/media/video/gspca/spca561.c b/drivers/media/video/gspca/spca561.c index 2ca509d..d2f689e 100644 --- a/drivers/media/video/gspca/spca561.c +++ b/drivers/media/video/gspca/spca561.c @@ -73,7 +73,7 @@ struct sd { #define AG_CNT_START 13 }; -static struct v4l2_pix_format sif_mode[] = { +static struct v4l2_pix_format sif_012a_mode[] = { {160, 120, V4L2_PIX_FMT_SGBRG8, V4L2_FIELD_NONE, .bytesperline = 160, .sizeimage = 160 * 120, @@ -96,6 +96,29 @@ static struct v4l2_pix_format sif_mode[] = { .priv = 0}, }; +static struct v4l2_pix_format sif_072a_mode[] = { + {160, 120, V4L2_PIX_FMT_SGBRG8, V4L2_FIELD_NONE, + .bytesperline = 160, + .sizeimage = 160 * 120, + .colorspace = V4L2_COLORSPACE_SRGB, + .priv = 3}, + {176, 144, V4L2_PIX_FMT_SGBRG8, V4L2_FIELD_NONE, + .bytesperline = 176, + .sizeimage = 176 * 144, + .colorspace = V4L2_COLORSPACE_SRGB, + .priv = 2}, + {320, 240, V4L2_PIX_FMT_SGBRG8, V4L2_FIELD_NONE, + .bytesperline = 320, + .sizeimage = 320 * 240, + .colorspace = V4L2_COLORSPACE_SRGB, + .priv = 1}, + {352, 288, V4L2_PIX_FMT_SGBRG8, V4L2_FIELD_NONE, + .bytesperline = 352, + .sizeimage = 352 * 288, + .colorspace = V4L2_COLORSPACE_SRGB, + .priv = 0}, +}; + /* * Initialization data * I'm not very sure how to split initialization from open data @@ -546,10 +569,15 @@ static int sd_config(struct gspca_dev *gspca_dev, cam = &gspca_dev->cam; cam->epaddr = 0x01; gspca_dev->nbalt = 7 + 1; /* choose alternate 7 first */ - cam->cam_mode = sif_mode; - cam->nmodes = ARRAY_SIZE(sif_mode); sd->chip_revision = id->driver_info; + if (sd->chip_revision == Rev012A) { + cam->cam_mode = sif_012a_mode; + cam->nmodes = ARRAY_SIZE(sif_012a_mode); + } else { + cam->cam_mode = sif_072a_mode; + cam->nmodes = ARRAY_SIZE(sif_072a_mode); + } sd->brightness = BRIGHTNESS_DEF; sd->contrast = CONTRAST_DEF; sd->white = WHITE_DEF; @@ -833,8 +861,9 @@ static void sd_pkt_scan(struct gspca_dev *gspca_dev, frame, data, len); } else { /* raw bayer (with a header, which we skip) */ - data += 20; - len -= 20; +/*fixme: is this specific to the rev012a? */ + data += 16; + len -= 16; gspca_frame_add(gspca_dev, FIRST_PACKET, frame, data, len); } -- cgit v0.10.2 From 0fc23d20699a6a3b7e34b3be2cc5e60317ba7849 Mon Sep 17 00:00:00 2001 From: Hans de Goede Date: Thu, 4 Sep 2008 16:22:57 -0300 Subject: V4L/DVB (8873): gspca: Bad image offset with rev012a of spca561 and adjust exposure. -Make raw bayer header size change from 20 to 16 affect rev072a only, my 2 rev012a cams both have a header size of 20 -While testing this I also tested the new exposure setting (good work on finding the register JF), and after quite a bit of testing have found out the exact meaning of the register, this patch modifies setexposure to control the exposure over a much wider range. Signed-off-by: Hans de Goede Signed-off-by: Jean-Francois Moine Signed-off-by: Mauro Carvalho Chehab diff --git a/drivers/media/video/gspca/spca561.c b/drivers/media/video/gspca/spca561.c index d2f689e..1c29c27 100644 --- a/drivers/media/video/gspca/spca561.c +++ b/drivers/media/video/gspca/spca561.c @@ -38,9 +38,9 @@ struct sd { #define CONTRAST_MAX 0x3fff __u16 exposure; /* rev12a only */ -#define EXPOSURE_MIN 0 +#define EXPOSURE_MIN 1 #define EXPOSURE_DEF 200 -#define EXPOSURE_MAX 762 +#define EXPOSURE_MAX (4095 - 900) /* see set_exposure */ __u8 brightness; /* rev72a only */ #define BRIGHTNESS_MIN 0 @@ -648,9 +648,31 @@ static void setexposure(struct gspca_dev *gspca_dev) { struct sd *sd = (struct sd *) gspca_dev; int expo; + int clock_divider; __u8 data[2]; - expo = sd->exposure + 0x20a8; /* from test */ + /* Register 0x8309 controls exposure for the spca561, + the basic exposure setting goes from 1-2047, where 1 is completely + dark and 2047 is very bright. It not only influences exposure but + also the framerate (to allow for longer exposure) from 1 - 300 it + only raises the exposure time then from 300 - 600 it halves the + framerate to be able to further raise the exposure time and for every + 300 more it halves the framerate again. This allows for a maximum + exposure time of circa 0.2 - 0.25 seconds (30 / (2000/3000) fps). + Sometimes this is not enough, the 1-2047 uses bits 0-10, bits 11-12 + configure a divider for the base framerate which us used at the + exposure setting of 1-300. These bits configure the base framerate + according to the following formula: fps = 60 / (value + 2) */ + if (sd->exposure < 2048) { + expo = sd->exposure; + clock_divider = 0; + } else { + /* Add 900 to make the 0 setting of the second part of the + exposure equal to the 2047 setting of the first part. */ + expo = (sd->exposure - 2048) + 900; + clock_divider = 3; + } + expo |= clock_divider << 11; data[0] = expo; data[1] = expo >> 8; reg_w_buf(gspca_dev, 0x8309, data, 2); @@ -680,23 +702,11 @@ static void setautogain(struct gspca_dev *gspca_dev) static void sd_start_12a(struct gspca_dev *gspca_dev) { struct usb_device *dev = gspca_dev->dev; - int Clck; + int Clck = 0x8a; /* lower 0x8X values lead to fps > 30 */ __u8 Reg8307[] = { 0xaa, 0x00 }; int mode; mode = gspca_dev->cam.cam_mode[(int) gspca_dev->curr_mode].priv; - switch (mode) { - case 0: - case 1: - Clck = 0x8a; - break; - case 2: - Clck = 0x85; - break; - default: - Clck = 0x83; - break; - } if (mode <= 1) { /* Use compression on 320x240 and above */ reg_w_val(dev, 0x8500, 0x10 | mode); @@ -714,6 +724,7 @@ static void sd_start_12a(struct gspca_dev *gspca_dev) setcontrast(gspca_dev); setwhite(gspca_dev); setautogain(gspca_dev); + setexposure(gspca_dev); } static void sd_start_72a(struct gspca_dev *gspca_dev) { @@ -849,6 +860,8 @@ static void sd_pkt_scan(struct gspca_dev *gspca_dev, __u8 *data, /* isoc packet */ int len) /* iso packet length */ { + struct sd *sd = (struct sd *) gspca_dev; + switch (data[0]) { case 0: /* start of frame */ frame = gspca_frame_add(gspca_dev, LAST_PACKET, frame, @@ -861,9 +874,13 @@ static void sd_pkt_scan(struct gspca_dev *gspca_dev, frame, data, len); } else { /* raw bayer (with a header, which we skip) */ -/*fixme: is this specific to the rev012a? */ - data += 16; - len -= 16; + if (sd->chip_revision == Rev012A) { + data += 20; + len -= 20; + } else { + data += 16; + len -= 16; + } gspca_frame_add(gspca_dev, FIRST_PACKET, frame, data, len); } -- cgit v0.10.2 From 4cce1655b26a4df1e619b2aa3d2eea1b7a6e906c Mon Sep 17 00:00:00 2001 From: Hans de Goede Date: Thu, 4 Sep 2008 16:22:57 -0300 Subject: V4L/DVB (8874): gspca: Adjust hstart for sn9c103/ov7630 and update usb-id's. - Adjust hstart in ov7630 on sn9c103 initdata to shift bayer pattern, this is the same change as done for the other initdata tables in a previous patch. - Assign usb-id's for the ov7630 + sn9c103 to gspca if gspca and sn9c102 drivers are both enabled. Signed-off-by: Hans de Goede Signed-off-by: Jean-Francois Moine Signed-off-by: Mauro Carvalho Chehab diff --git a/drivers/media/video/gspca/sonixb.c b/drivers/media/video/gspca/sonixb.c index 64bc758..5dd78c6 100644 --- a/drivers/media/video/gspca/sonixb.c +++ b/drivers/media/video/gspca/sonixb.c @@ -348,7 +348,7 @@ static const __u8 initOv7630[] = { static const __u8 initOv7630_3[] = { 0x44, 0x44, 0x00, 0x1a, 0x20, 0x20, 0x20, 0x80, /* r01 .. r08 */ 0x21, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x04, /* r09 .. r10 */ - 0x00, 0x01, 0x01, 0x0a, /* r11 .. r14 */ + 0x00, 0x02, 0x01, 0x0a, /* r11 .. r14 */ 0x28, 0x1e, /* H & V sizes r15 .. r16 */ 0x68, 0x8f, MCK_INIT1, /* r17 .. r19 */ 0x1d, 0x10, 0x02, 0x03, 0x0f, 0x0c, 0x00, /* r1a .. r20 */ @@ -1230,10 +1230,12 @@ static __devinitdata struct usb_device_id device_table[] = { {USB_DEVICE(0x0c45, 0x602d), SB(HV7131R, 102)}, #if !defined CONFIG_USB_SN9C102 && !defined CONFIG_USB_SN9C102_MODULE {USB_DEVICE(0x0c45, 0x602e), SB(OV7630, 102)}, +#endif {USB_DEVICE(0x0c45, 0x608f), SB(OV7630, 103)}, +#if !defined CONFIG_USB_SN9C102 && !defined CONFIG_USB_SN9C102_MODULE {USB_DEVICE(0x0c45, 0x60af), SB(PAS202, 103)}, - {USB_DEVICE(0x0c45, 0x60b0), SB(OV7630, 103)}, #endif + {USB_DEVICE(0x0c45, 0x60b0), SB(OV7630, 103)}, {} }; MODULE_DEVICE_TABLE(usb, device_table); diff --git a/drivers/media/video/sn9c102/sn9c102_devtable.h b/drivers/media/video/sn9c102/sn9c102_devtable.h index f474914..90a401d 100644 --- a/drivers/media/video/sn9c102/sn9c102_devtable.h +++ b/drivers/media/video/sn9c102/sn9c102_devtable.h @@ -68,7 +68,9 @@ static const struct usb_device_id sn9c102_id_table[] = { { SN9C102_USB_DEVICE(0x0c45, 0x608b, BRIDGE_SN9C103), }, { SN9C102_USB_DEVICE(0x0c45, 0x608c, BRIDGE_SN9C103), }, /* { SN9C102_USB_DEVICE(0x0c45, 0x608e, BRIDGE_SN9C103), }, CISVF10 */ +#if !defined CONFIG_USB_GSPCA && !defined CONFIG_USB_GSPCA_MODULE { SN9C102_USB_DEVICE(0x0c45, 0x608f, BRIDGE_SN9C103), }, +#endif { SN9C102_USB_DEVICE(0x0c45, 0x60a0, BRIDGE_SN9C103), }, { SN9C102_USB_DEVICE(0x0c45, 0x60a2, BRIDGE_SN9C103), }, { SN9C102_USB_DEVICE(0x0c45, 0x60a3, BRIDGE_SN9C103), }, @@ -78,7 +80,9 @@ static const struct usb_device_id sn9c102_id_table[] = { { SN9C102_USB_DEVICE(0x0c45, 0x60ac, BRIDGE_SN9C103), }, { SN9C102_USB_DEVICE(0x0c45, 0x60ae, BRIDGE_SN9C103), }, { SN9C102_USB_DEVICE(0x0c45, 0x60af, BRIDGE_SN9C103), }, +#if !defined CONFIG_USB_GSPCA && !defined CONFIG_USB_GSPCA_MODULE { SN9C102_USB_DEVICE(0x0c45, 0x60b0, BRIDGE_SN9C103), }, +#endif { SN9C102_USB_DEVICE(0x0c45, 0x60b2, BRIDGE_SN9C103), }, { SN9C102_USB_DEVICE(0x0c45, 0x60b3, BRIDGE_SN9C103), }, { SN9C102_USB_DEVICE(0x0c45, 0x60b8, BRIDGE_SN9C103), }, -- cgit v0.10.2 From 65846909d684d75906269df4f5f3474e1fef568b Mon Sep 17 00:00:00 2001 From: Russell King Date: Wed, 3 Sep 2008 23:46:18 +0100 Subject: [ARM] omap: fix virtual vs physical address space confusions mcbsp is confused as to what takes a physical or virtual address. Fix the two instances where it gets it wrong. Acked-by: Tony Lindgren Signed-off-by: Russell King diff --git a/arch/arm/mach-omap1/mcbsp.c b/arch/arm/mach-omap1/mcbsp.c index 826010d..2baeaeb 100644 --- a/arch/arm/mach-omap1/mcbsp.c +++ b/arch/arm/mach-omap1/mcbsp.c @@ -159,6 +159,7 @@ static struct omap_mcbsp_ops omap1_mcbsp_ops = { #ifdef CONFIG_ARCH_OMAP730 static struct omap_mcbsp_platform_data omap730_mcbsp_pdata[] = { { + .phys_base = OMAP730_MCBSP1_BASE, .virt_base = io_p2v(OMAP730_MCBSP1_BASE), .dma_rx_sync = OMAP_DMA_MCBSP1_RX, .dma_tx_sync = OMAP_DMA_MCBSP1_TX, @@ -167,6 +168,7 @@ static struct omap_mcbsp_platform_data omap730_mcbsp_pdata[] = { .ops = &omap1_mcbsp_ops, }, { + .phys_base = OMAP730_MCBSP2_BASE, .virt_base = io_p2v(OMAP730_MCBSP2_BASE), .dma_rx_sync = OMAP_DMA_MCBSP3_RX, .dma_tx_sync = OMAP_DMA_MCBSP3_TX, @@ -184,6 +186,7 @@ static struct omap_mcbsp_platform_data omap730_mcbsp_pdata[] = { #ifdef CONFIG_ARCH_OMAP15XX static struct omap_mcbsp_platform_data omap15xx_mcbsp_pdata[] = { { + .phys_base = OMAP1510_MCBSP1_BASE, .virt_base = OMAP1510_MCBSP1_BASE, .dma_rx_sync = OMAP_DMA_MCBSP1_RX, .dma_tx_sync = OMAP_DMA_MCBSP1_TX, @@ -193,6 +196,7 @@ static struct omap_mcbsp_platform_data omap15xx_mcbsp_pdata[] = { .clk_name = "mcbsp_clk", }, { + .phys_base = OMAP1510_MCBSP2_BASE, .virt_base = io_p2v(OMAP1510_MCBSP2_BASE), .dma_rx_sync = OMAP_DMA_MCBSP2_RX, .dma_tx_sync = OMAP_DMA_MCBSP2_TX, @@ -201,6 +205,7 @@ static struct omap_mcbsp_platform_data omap15xx_mcbsp_pdata[] = { .ops = &omap1_mcbsp_ops, }, { + .phys_base = OMAP1510_MCBSP3_BASE, .virt_base = OMAP1510_MCBSP3_BASE, .dma_rx_sync = OMAP_DMA_MCBSP3_RX, .dma_tx_sync = OMAP_DMA_MCBSP3_TX, @@ -219,6 +224,7 @@ static struct omap_mcbsp_platform_data omap15xx_mcbsp_pdata[] = { #ifdef CONFIG_ARCH_OMAP16XX static struct omap_mcbsp_platform_data omap16xx_mcbsp_pdata[] = { { + .phys_base = OMAP1610_MCBSP1_BASE, .virt_base = OMAP1610_MCBSP1_BASE, .dma_rx_sync = OMAP_DMA_MCBSP1_RX, .dma_tx_sync = OMAP_DMA_MCBSP1_TX, @@ -228,6 +234,7 @@ static struct omap_mcbsp_platform_data omap16xx_mcbsp_pdata[] = { .clk_name = "mcbsp_clk", }, { + .phys_base = OMAP1610_MCBSP2_BASE, .virt_base = io_p2v(OMAP1610_MCBSP2_BASE), .dma_rx_sync = OMAP_DMA_MCBSP2_RX, .dma_tx_sync = OMAP_DMA_MCBSP2_TX, @@ -236,6 +243,7 @@ static struct omap_mcbsp_platform_data omap16xx_mcbsp_pdata[] = { .ops = &omap1_mcbsp_ops, }, { + .phys_base = OMAP1610_MCBSP3_BASE, .virt_base = OMAP1610_MCBSP3_BASE, .dma_rx_sync = OMAP_DMA_MCBSP3_RX, .dma_tx_sync = OMAP_DMA_MCBSP3_TX, diff --git a/arch/arm/mach-omap2/mcbsp.c b/arch/arm/mach-omap2/mcbsp.c index 27eb6e3..b261f1f 100644 --- a/arch/arm/mach-omap2/mcbsp.c +++ b/arch/arm/mach-omap2/mcbsp.c @@ -134,6 +134,7 @@ static struct omap_mcbsp_ops omap2_mcbsp_ops = { #ifdef CONFIG_ARCH_OMAP24XX static struct omap_mcbsp_platform_data omap24xx_mcbsp_pdata[] = { { + .phys_base = OMAP24XX_MCBSP1_BASE, .virt_base = IO_ADDRESS(OMAP24XX_MCBSP1_BASE), .dma_rx_sync = OMAP24XX_DMA_MCBSP1_RX, .dma_tx_sync = OMAP24XX_DMA_MCBSP1_TX, @@ -143,6 +144,7 @@ static struct omap_mcbsp_platform_data omap24xx_mcbsp_pdata[] = { .clk_name = "mcbsp_clk", }, { + .phys_base = OMAP24XX_MCBSP2_BASE, .virt_base = IO_ADDRESS(OMAP24XX_MCBSP2_BASE), .dma_rx_sync = OMAP24XX_DMA_MCBSP2_RX, .dma_tx_sync = OMAP24XX_DMA_MCBSP2_TX, @@ -161,6 +163,7 @@ static struct omap_mcbsp_platform_data omap24xx_mcbsp_pdata[] = { #ifdef CONFIG_ARCH_OMAP34XX static struct omap_mcbsp_platform_data omap34xx_mcbsp_pdata[] = { { + .phys_base = OMAP34XX_MCBSP1_BASE, .virt_base = IO_ADDRESS(OMAP34XX_MCBSP1_BASE), .dma_rx_sync = OMAP24XX_DMA_MCBSP1_RX, .dma_tx_sync = OMAP24XX_DMA_MCBSP1_TX, @@ -170,6 +173,7 @@ static struct omap_mcbsp_platform_data omap34xx_mcbsp_pdata[] = { .clk_name = "mcbsp_clk", }, { + .phys_base = OMAP34XX_MCBSP2_BASE, .virt_base = IO_ADDRESS(OMAP34XX_MCBSP2_BASE), .dma_rx_sync = OMAP24XX_DMA_MCBSP2_RX, .dma_tx_sync = OMAP24XX_DMA_MCBSP2_TX, diff --git a/arch/arm/plat-omap/include/mach/mcbsp.h b/arch/arm/plat-omap/include/mach/mcbsp.h index 6eb44a9..8fdb95e 100644 --- a/arch/arm/plat-omap/include/mach/mcbsp.h +++ b/arch/arm/plat-omap/include/mach/mcbsp.h @@ -315,6 +315,7 @@ struct omap_mcbsp_ops { }; struct omap_mcbsp_platform_data { + unsigned long phys_base; u32 virt_base; u8 dma_rx_sync, dma_tx_sync; u16 rx_irq, tx_irq; @@ -324,6 +325,7 @@ struct omap_mcbsp_platform_data { struct omap_mcbsp { struct device *dev; + unsigned long phys_base; u32 io_base; u8 id; u8 free; diff --git a/arch/arm/plat-omap/mcbsp.c b/arch/arm/plat-omap/mcbsp.c index d084405..014d265 100644 --- a/arch/arm/plat-omap/mcbsp.c +++ b/arch/arm/plat-omap/mcbsp.c @@ -651,7 +651,7 @@ int omap_mcbsp_xmit_buffer(unsigned int id, dma_addr_t buffer, omap_set_dma_dest_params(mcbsp[id].dma_tx_lch, src_port, OMAP_DMA_AMODE_CONSTANT, - mcbsp[id].io_base + OMAP_MCBSP_REG_DXR1, + mcbsp[id].phys_base + OMAP_MCBSP_REG_DXR1, 0, 0); omap_set_dma_src_params(mcbsp[id].dma_tx_lch, @@ -712,7 +712,7 @@ int omap_mcbsp_recv_buffer(unsigned int id, dma_addr_t buffer, omap_set_dma_src_params(mcbsp[id].dma_rx_lch, src_port, OMAP_DMA_AMODE_CONSTANT, - mcbsp[id].io_base + OMAP_MCBSP_REG_DRR1, + mcbsp[id].phys_base + OMAP_MCBSP_REG_DRR1, 0, 0); omap_set_dma_dest_params(mcbsp[id].dma_rx_lch, @@ -830,6 +830,7 @@ static int __init omap_mcbsp_probe(struct platform_device *pdev) mcbsp[id].dma_tx_lch = -1; mcbsp[id].dma_rx_lch = -1; + mcbsp[id].phys_base = pdata->phys_base; mcbsp[id].io_base = pdata->virt_base; /* Default I/O is IRQ based */ mcbsp[id].io_type = OMAP_MCBSP_IRQ_IO; -- cgit v0.10.2 From db210426d48998ed412f267b28cf6e62ea0496a8 Mon Sep 17 00:00:00 2001 From: Thierry MERLE Date: Mon, 1 Sep 2008 17:28:57 -0300 Subject: V4L/DVB (8876): budget: udelay changed to mdelay budget.ko fails to build on ARM with: ERROR: "__bad_udelay" [drivers/media/dvb/ttpci/budget.ko] undefined! make[1]: *** [__modpost] Error 1 __bad_udelay is specifically designed on ARM to fail when udelay is called in a bad way. arch/arm/include/asm/delay.h has this to say about __bad_udelay: /* * This function intentionally does not exist; if you see references to * it, it means that you're calling udelay() with an out of range value. * * With currently imposed limits, this means that we support a max delay * of 2000us. Further limits: HZ<=1000 and bogomips<=3355 */ extern void __bad_udelay(void); Solution is to replace udelay by a mdelay and udelay with value less than 2000 Acked-by: Oliver Endriss Signed-off-by: Thierry MERLE Signed-off-by: Mauro Carvalho Chehab diff --git a/drivers/media/dvb/ttpci/budget-patch.c b/drivers/media/dvb/ttpci/budget-patch.c index 39bd0a2..aa5ed4e 100644 --- a/drivers/media/dvb/ttpci/budget-patch.c +++ b/drivers/media/dvb/ttpci/budget-patch.c @@ -116,7 +116,8 @@ static int SendDiSEqCMsg (struct budget *budget, int len, u8 *msg, unsigned long DiseqcSendByte(budget, 0xff); else { saa7146_setgpio(dev, 3, SAA7146_GPIO_OUTHI); - udelay(12500); + mdelay(12); + udelay(500); saa7146_setgpio(dev, 3, SAA7146_GPIO_OUTLO); } msleep(20); diff --git a/drivers/media/dvb/ttpci/budget.c b/drivers/media/dvb/ttpci/budget.c index 2293d80..f006899 100644 --- a/drivers/media/dvb/ttpci/budget.c +++ b/drivers/media/dvb/ttpci/budget.c @@ -108,7 +108,8 @@ static int SendDiSEqCMsg (struct budget *budget, int len, u8 *msg, unsigned long DiseqcSendByte(budget, 0xff); else { saa7146_setgpio(dev, 3, SAA7146_GPIO_OUTHI); - udelay(12500); + mdelay(12); + udelay(500); saa7146_setgpio(dev, 3, SAA7146_GPIO_OUTLO); } msleep(20); -- cgit v0.10.2 From c4e3fd940c7081a0332e9b4ea6485744075067b0 Mon Sep 17 00:00:00 2001 From: Thierry MERLE Date: Mon, 1 Sep 2008 17:32:10 -0300 Subject: V4L/DVB (8877): b2c2 and bt8xx: udelay to mdelay b2c2-flexcop, dvb/bt8xx and video/bt8xx fails to build on ARM with: __bad_udelay is specifically designed on ARM to fail when udelay is called in a bad way. arch/arm/include/asm/delay.h has this to say about __bad_udelay: /* * This function intentionally does not exist; if you see references to * it, it means that you're calling udelay() with an out of range value. * * With currently imposed limits, this means that we support a max delay * of 2000us. Further limits: HZ<=1000 and bogomips<=3355 */ extern void __bad_udelay(void); Solution is to replace udelay by a mdelay and udelay with value less than 2000 Signed-off-by: Thierry MERLE Signed-off-by: Mauro Carvalho Chehab diff --git a/drivers/media/dvb/b2c2/flexcop-fe-tuner.c b/drivers/media/dvb/b2c2/flexcop-fe-tuner.c index f9d0876..4eed783 100644 --- a/drivers/media/dvb/b2c2/flexcop-fe-tuner.c +++ b/drivers/media/dvb/b2c2/flexcop-fe-tuner.c @@ -137,7 +137,8 @@ static int flexcop_send_diseqc_msg(struct dvb_frontend* fe, int len, u8 *msg, un flexcop_diseqc_send_byte(fe, 0xff); else { flexcop_set_tone(fe, SEC_TONE_ON); - udelay(12500); + mdelay(12); + udelay(500); flexcop_set_tone(fe, SEC_TONE_OFF); } msleep(20); diff --git a/drivers/media/dvb/bt8xx/dst.c b/drivers/media/dvb/bt8xx/dst.c index a763756..aa3db57 100644 --- a/drivers/media/dvb/bt8xx/dst.c +++ b/drivers/media/dvb/bt8xx/dst.c @@ -1244,7 +1244,7 @@ static int dst_command(struct dst_state *state, u8 *data, u8 len) goto error; } if (state->type_flags & DST_TYPE_HAS_FW_1) - udelay(3000); + mdelay(3); if (read_dst(state, &reply, GET_ACK)) { dprintk(verbose, DST_DEBUG, 1, "Trying to recover.. "); if ((dst_error_recovery(state)) < 0) { @@ -1260,7 +1260,7 @@ static int dst_command(struct dst_state *state, u8 *data, u8 len) if (len >= 2 && data[0] == 0 && (data[1] == 1 || data[1] == 3)) goto error; if (state->type_flags & DST_TYPE_HAS_FW_1) - udelay(3000); + mdelay(3); else udelay(2000); if (!dst_wait_dst_ready(state, NO_DELAY)) diff --git a/drivers/media/video/bt8xx/bttv-cards.c b/drivers/media/video/bt8xx/bttv-cards.c index 9001de2..6081edc 100644 --- a/drivers/media/video/bt8xx/bttv-cards.c +++ b/drivers/media/video/bt8xx/bttv-cards.c @@ -4039,7 +4039,8 @@ static void __devinit boot_msp34xx(struct bttv *btv, int pin) gpio_inout(mask,mask); gpio_bits(mask,0); - udelay(2500); + mdelay(2); + udelay(500); gpio_bits(mask,mask); if (bttv_gpio) -- cgit v0.10.2 From 748c7f80acc266a54ade4d6863229402fd3cd363 Mon Sep 17 00:00:00 2001 From: Hans de Goede Date: Mon, 1 Sep 2008 15:28:23 -0300 Subject: V4L/DVB (8880): PATCH: Fix parents on some webcam drivers While doing some testing using Luca Risolia's sonix driver I noticed that the video device did not get ACL's set to allow access by locally logged in users, nor does it show up as a video device in lshal, causing cheese to not see it. This turns out to be caused by all of Luca Risolia's drivers not setting the parent member of the video_device struct. This patch fixes this. Cc: Luca Risolia Signed-off-by: Hans de Goede Signed-off-by: Mauro Carvalho Chehab diff --git a/drivers/media/video/et61x251/et61x251_core.c b/drivers/media/video/et61x251/et61x251_core.c index 2d170d1..8db2a05 100644 --- a/drivers/media/video/et61x251/et61x251_core.c +++ b/drivers/media/video/et61x251/et61x251_core.c @@ -2588,6 +2588,7 @@ et61x251_usb_probe(struct usb_interface* intf, const struct usb_device_id* id) cam->v4ldev->fops = &et61x251_fops; cam->v4ldev->minor = video_nr[dev_nr]; cam->v4ldev->release = video_device_release; + cam->v4ldev->parent = &udev->dev; video_set_drvdata(cam->v4ldev, cam); init_completion(&cam->probe); diff --git a/drivers/media/video/sn9c102/sn9c102_core.c b/drivers/media/video/sn9c102/sn9c102_core.c index 2340876..2da6938 100644 --- a/drivers/media/video/sn9c102/sn9c102_core.c +++ b/drivers/media/video/sn9c102/sn9c102_core.c @@ -3312,6 +3312,7 @@ sn9c102_usb_probe(struct usb_interface* intf, const struct usb_device_id* id) cam->v4ldev->fops = &sn9c102_fops; cam->v4ldev->minor = video_nr[dev_nr]; cam->v4ldev->release = video_device_release; + cam->v4ldev->parent = &udev->dev; init_completion(&cam->probe); diff --git a/drivers/media/video/zc0301/zc0301_core.c b/drivers/media/video/zc0301/zc0301_core.c index 550ce7b..0c32877 100644 --- a/drivers/media/video/zc0301/zc0301_core.c +++ b/drivers/media/video/zc0301/zc0301_core.c @@ -1988,6 +1988,7 @@ zc0301_usb_probe(struct usb_interface* intf, const struct usb_device_id* id) cam->v4ldev->fops = &zc0301_fops; cam->v4ldev->minor = video_nr[dev_nr]; cam->v4ldev->release = video_device_release; + cam->v4ldev->parent = &udev->dev; video_set_drvdata(cam->v4ldev, cam); init_completion(&cam->probe); -- cgit v0.10.2 From 8561098ff11d21f1a6a9a01fae2e68653928dbb5 Mon Sep 17 00:00:00 2001 From: Li Zefan Date: Tue, 2 Sep 2008 07:02:50 -0300 Subject: V4L/DVB (8881): gspca: After 'while (retry--) {...}', retry will be -1 but not 0. Signed-off-by: Li Zefan Signed-off-by: Jean-Francois Moine Signed-off-by: Mauro Carvalho Chehab diff --git a/drivers/media/video/gspca/conex.c b/drivers/media/video/gspca/conex.c index 8c91ffd..4d9f4cc 100644 --- a/drivers/media/video/gspca/conex.c +++ b/drivers/media/video/gspca/conex.c @@ -731,13 +731,13 @@ static void cx11646_jpeg(struct gspca_dev*gspca_dev) reg_w_val(gspca_dev, 0x0000, 0x00); /* wait for completion */ retry = 50; - while (retry--) { + do { reg_r(gspca_dev, 0x0002, 1); /* 0x07 until 0x00 */ if (gspca_dev->usb_buf[0] == 0x00) break; reg_w_val(gspca_dev, 0x0053, 0x00); - } + } while (--retry); if (retry == 0) PDEBUG(D_ERR, "Damned Errors sending jpeg Table"); /* send the qtable now */ diff --git a/drivers/media/video/gspca/spca561.c b/drivers/media/video/gspca/spca561.c index 1c29c27..cfbc9eb 100644 --- a/drivers/media/video/gspca/spca561.c +++ b/drivers/media/video/gspca/spca561.c @@ -223,11 +223,11 @@ static int i2c_read(struct gspca_dev *gspca_dev, __u16 reg, __u8 mode) reg_w_val(gspca_dev->dev, 0x8804, 0x92); reg_w_val(gspca_dev->dev, 0x8801, reg); reg_w_val(gspca_dev->dev, 0x8802, (mode | 0x01)); - while (retry--) { + do { reg_r(gspca_dev, 0x8803, 1); if (!gspca_dev->usb_buf) break; - } + } while (--retry); if (retry == 0) return -1; reg_r(gspca_dev, 0x8800, 1); -- cgit v0.10.2 From 9f43e3914dceb0f8191875b3cdf4325b48d0d70a Mon Sep 17 00:00:00 2001 From: Jeremy Kerr Date: Tue, 2 Sep 2008 11:57:09 +1000 Subject: powerpc/spufs: Fix multiple get_spu_context() Commit 8d5636fbca202f61fdb808fc9e20c0142291d802 introduced a reference count on SPU contexts during find_victim, but this may cause a leak in the reference count if we later find a better contender for a context to unschedule. Change the reference to after we've found our victim context, so we don't do the extra get_spu_context(). Signed-off-by: Jeremy Kerr diff --git a/arch/powerpc/platforms/cell/spufs/sched.c b/arch/powerpc/platforms/cell/spufs/sched.c index 1c1b627..9bb45c6 100644 --- a/arch/powerpc/platforms/cell/spufs/sched.c +++ b/arch/powerpc/platforms/cell/spufs/sched.c @@ -643,9 +643,10 @@ static struct spu *find_victim(struct spu_context *ctx) !(tmp->flags & SPU_CREATE_NOSCHED) && (!victim || tmp->prio > victim->prio)) { victim = spu->ctx; - get_spu_context(victim); } } + if (victim) + get_spu_context(victim); mutex_unlock(&cbe_spu_info[node].list_mutex); if (victim) { -- cgit v0.10.2 From b65fe0356b5b732d7e1e0224c6a1cf2eb5255984 Mon Sep 17 00:00:00 2001 From: Jeremy Kerr Date: Thu, 4 Sep 2008 15:02:47 +1000 Subject: powerpc/spufs: Fix race for a free SPU We currently have a race for a free SPE. With one thread doing a spu_yield(), and another doing a spu_activate(): thread 1 thread 2 spu_yield(oldctx) spu_activate(ctx) __spu_deactivate(oldctx) spu_unschedule(oldctx, spu) spu->alloc_state = SPU_FREE spu = spu_get_idle(ctx) - searches for a SPE in state SPU_FREE, gets the context just freed by thread 1 spu_schedule(ctx, spu) spu->alloc_state = SPU_USED spu_schedule(newctx, spu) - assumes spu is still free - tries to schedule context on already-used spu This change introduces a 'free_spu' flag to spu_unschedule, to indicate whether or not the function should free the spu after descheduling the context. We only set this flag if we're not going to re-schedule another context on this SPU. Add a comment to document this behaviour. Signed-off-by: Jeremy Kerr diff --git a/arch/powerpc/platforms/cell/spufs/sched.c b/arch/powerpc/platforms/cell/spufs/sched.c index 9bb45c6..897c740 100644 --- a/arch/powerpc/platforms/cell/spufs/sched.c +++ b/arch/powerpc/platforms/cell/spufs/sched.c @@ -732,13 +732,28 @@ static void spu_schedule(struct spu *spu, struct spu_context *ctx) spu_release(ctx); } -static void spu_unschedule(struct spu *spu, struct spu_context *ctx) +/** + * spu_unschedule - remove a context from a spu, and possibly release it. + * @spu: The SPU to unschedule from + * @ctx: The context currently scheduled on the SPU + * @free_spu Whether to free the SPU for other contexts + * + * Unbinds the context @ctx from the SPU @spu. If @free_spu is non-zero, the + * SPU is made available for other contexts (ie, may be returned by + * spu_get_idle). If this is zero, the caller is expected to schedule another + * context to this spu. + * + * Should be called with ctx->state_mutex held. + */ +static void spu_unschedule(struct spu *spu, struct spu_context *ctx, + int free_spu) { int node = spu->node; mutex_lock(&cbe_spu_info[node].list_mutex); cbe_spu_info[node].nr_active--; - spu->alloc_state = SPU_FREE; + if (free_spu) + spu->alloc_state = SPU_FREE; spu_unbind_context(spu, ctx); ctx->stats.invol_ctx_switch++; spu->stats.invol_ctx_switch++; @@ -838,7 +853,7 @@ static int __spu_deactivate(struct spu_context *ctx, int force, int max_prio) if (spu) { new = grab_runnable_context(max_prio, spu->node); if (new || force) { - spu_unschedule(spu, ctx); + spu_unschedule(spu, ctx, new == NULL); if (new) { if (new->flags & SPU_CREATE_NOSCHED) wake_up(&new->stop_wq); @@ -911,7 +926,7 @@ static noinline void spusched_tick(struct spu_context *ctx) new = grab_runnable_context(ctx->prio + 1, spu->node); if (new) { - spu_unschedule(spu, ctx); + spu_unschedule(spu, ctx, 0); if (test_bit(SPU_SCHED_SPU_RUN, &ctx->sched_flags)) spu_add_to_rq(ctx); } else { -- cgit v0.10.2 From 158e0fb6028a2329425d8287b1b2402a12ed4f28 Mon Sep 17 00:00:00 2001 From: Henrik Rydberg Date: Thu, 4 Sep 2008 22:20:10 -0400 Subject: Input: bcm5974 - small formatting cleanup Signed-off-by: Henrik Rydberg Signed-off-by: Dmitry Torokhov diff --git a/drivers/input/mouse/bcm5974.c b/drivers/input/mouse/bcm5974.c index 2ec921b..ae78bb8 100644 --- a/drivers/input/mouse/bcm5974.c +++ b/drivers/input/mouse/bcm5974.c @@ -63,7 +63,7 @@ } /* table of devices that work with this driver */ -static const struct usb_device_id bcm5974_table [] = { +static const struct usb_device_id bcm5974_table[] = { /* MacbookAir1.1 */ BCM5974_DEVICE(USB_DEVICE_ID_APPLE_WELLSPRING_ANSI), BCM5974_DEVICE(USB_DEVICE_ID_APPLE_WELLSPRING_ISO), -- cgit v0.10.2 From 75e21e3f3bb2b4a41bb0646a4d54eef27eb36ca5 Mon Sep 17 00:00:00 2001 From: Henrik Rydberg Date: Thu, 4 Sep 2008 22:28:23 -0400 Subject: Input: bcm5974 - improve finger tracking and counting The problem of finger tracking, i.e., when to switch focus from one finger to another on the trackpad, has been improved by utilizing more information from the bcm5974 chip output. This results in less pointer hopping when many fingers are on the trackpad. In addition, a finger counting method based on pressure information from all fingers is introduced. Together with a pressure hysteresis window, this yields a more stable counting of the number of fingers on the trackpad. Signed-off-by: Henrik Rydberg Signed-off-by: Dmitry Torokhov diff --git a/drivers/input/mouse/bcm5974.c b/drivers/input/mouse/bcm5974.c index ae78bb8..8568211 100644 --- a/drivers/input/mouse/bcm5974.c +++ b/drivers/input/mouse/bcm5974.c @@ -105,7 +105,7 @@ struct tp_header { /* trackpad finger structure */ struct tp_finger { - __le16 origin; /* left/right origin? */ + __le16 origin; /* zero when switching track finger */ __le16 abs_x; /* absolute x coodinate */ __le16 abs_y; /* absolute y coodinate */ __le16 rel_x; /* relative x coodinate */ @@ -159,6 +159,7 @@ struct bcm5974 { struct bt_data *bt_data; /* button transferred data */ struct urb *tp_urb; /* trackpad usb request block */ struct tp_data *tp_data; /* trackpad transferred data */ + int fingers; /* number of fingers on trackpad */ }; /* logical dimensions */ @@ -172,6 +173,10 @@ struct bcm5974 { #define SN_WIDTH 100 /* width signal-to-noise ratio */ #define SN_COORD 250 /* coordinate signal-to-noise ratio */ +/* pressure thresholds */ +#define PRESSURE_LOW (2 * DIM_PRESSURE / SN_PRESSURE) +#define PRESSURE_HIGH (3 * PRESSURE_LOW) + /* device constants */ static const struct bcm5974_config bcm5974_config_table[] = { { @@ -273,32 +278,65 @@ static int report_tp_state(struct bcm5974 *dev, int size) const struct tp_finger *f = dev->tp_data->finger; struct input_dev *input = dev->input; const int fingers = (size - 26) / 28; - int p = 0, w, x, y, n = 0; + int raw_p, raw_w, raw_x, raw_y; + int ptest = 0, origin = 0, nmin = 0, nmax = 0; + int abs_p = 0, abs_w = 0, abs_x = 0, abs_y = 0; if (size < 26 || (size - 26) % 28 != 0) return -EIO; + /* always track the first finger; when detached, start over */ if (fingers) { - p = raw2int(f->force_major); - w = raw2int(f->size_major); - x = raw2int(f->abs_x); - y = raw2int(f->abs_y); - n = p > 0 ? fingers : 0; + raw_p = raw2int(f->force_major); + raw_w = raw2int(f->size_major); + raw_x = raw2int(f->abs_x); + raw_y = raw2int(f->abs_y); dprintk(9, - "bcm5974: p: %+05d w: %+05d x: %+05d y: %+05d n: %d\n", - p, w, x, y, n); + "bcm5974: raw: p: %+05d w: %+05d x: %+05d y: %+05d\n", + raw_p, raw_w, raw_x, raw_y); + + ptest = int2bound(&c->p, raw_p); + origin = raw2int(f->origin); + } - input_report_abs(input, ABS_TOOL_WIDTH, int2bound(&c->w, w)); - input_report_abs(input, ABS_X, int2bound(&c->x, x - c->x.devmin)); - input_report_abs(input, ABS_Y, int2bound(&c->y, c->y.devmax - y)); + /* while tracking finger still valid, count all fingers */ + if (ptest > PRESSURE_LOW && origin) { + abs_p = ptest; + abs_w = int2bound(&c->w, raw_w); + abs_x = int2bound(&c->x, raw_x - c->x.devmin); + abs_y = int2bound(&c->y, c->y.devmax - raw_y); + for (; f != dev->tp_data->finger + fingers; f++) { + ptest = int2bound(&c->p, raw2int(f->force_major)); + if (ptest > PRESSURE_LOW) + nmax++; + if (ptest > PRESSURE_HIGH) + nmin++; + } } - input_report_abs(input, ABS_PRESSURE, int2bound(&c->p, p)); + if (dev->fingers < nmin) + dev->fingers = nmin; + if (dev->fingers > nmax) + dev->fingers = nmax; + + input_report_key(input, BTN_TOOL_FINGER, dev->fingers == 1); + input_report_key(input, BTN_TOOL_DOUBLETAP, dev->fingers == 2); + input_report_key(input, BTN_TOOL_TRIPLETAP, dev->fingers > 2); - input_report_key(input, BTN_TOOL_FINGER, n == 1); - input_report_key(input, BTN_TOOL_DOUBLETAP, n == 2); - input_report_key(input, BTN_TOOL_TRIPLETAP, n > 2); + input_report_abs(input, ABS_PRESSURE, abs_p); + input_report_abs(input, ABS_TOOL_WIDTH, abs_w); + + if (abs_p) { + input_report_abs(input, ABS_X, abs_x); + input_report_abs(input, ABS_Y, abs_y); + + dprintk(8, + "bcm5974: abs: p: %+05d w: %+05d x: %+05d y: %+05d " + "nmin: %d nmax: %d n: %d\n", + abs_p, abs_w, abs_x, abs_y, nmin, nmax, dev->fingers); + + } input_sync(input); -- cgit v0.10.2 From a6821f345fd508b17f5ce310b677b37aefb028dc Mon Sep 17 00:00:00 2001 From: Henrik Rydberg Date: Thu, 4 Sep 2008 22:28:31 -0400 Subject: Input: bcm5974 - add BTN_TOUCH event for mousedev benefit The mousedev driver requires the use of BTN_TOUCH events to process ABS_X and ABS_Y events properly, which is what is needed for the bcm5974-based apple computers to have a functional pointer out-of-the-box. Signed-off-by: Henrik Rydberg Signed-off-by: Dmitry Torokhov diff --git a/drivers/input/mouse/bcm5974.c b/drivers/input/mouse/bcm5974.c index 8568211..18f4d7f 100644 --- a/drivers/input/mouse/bcm5974.c +++ b/drivers/input/mouse/bcm5974.c @@ -253,6 +253,7 @@ static void setup_events_to_report(struct input_dev *input_dev, 0, cfg->y.dim, cfg->y.fuzz, 0); __set_bit(EV_KEY, input_dev->evbit); + __set_bit(BTN_TOUCH, input_dev->keybit); __set_bit(BTN_TOOL_FINGER, input_dev->keybit); __set_bit(BTN_TOOL_DOUBLETAP, input_dev->keybit); __set_bit(BTN_TOOL_TRIPLETAP, input_dev->keybit); @@ -320,6 +321,7 @@ static int report_tp_state(struct bcm5974 *dev, int size) if (dev->fingers > nmax) dev->fingers = nmax; + input_report_key(input, BTN_TOUCH, dev->fingers > 0); input_report_key(input, BTN_TOOL_FINGER, dev->fingers == 1); input_report_key(input, BTN_TOOL_DOUBLETAP, dev->fingers == 2); input_report_key(input, BTN_TOOL_TRIPLETAP, dev->fingers > 2); -- cgit v0.10.2 From 9ce1ca284a322ba6f9d691136a29c9cfe381e1fc Mon Sep 17 00:00:00 2001 From: Jiri Kosina Date: Thu, 4 Sep 2008 22:28:48 -0400 Subject: Input: i8042 - make Lenovo 3000 N100 blacklist entry more specific Apparently, there are more different versions of Lenovo 3000 N100, some of them working properly with active mux, and some of them requiring it being switched off. This patch applies 'nomux' only to the specific product name that is reported to behave badly unless 'nomux' is specified. Signed-off-by: Jiri Kosina Signed-off-by: Dmitry Torokhov diff --git a/drivers/input/serio/i8042-x86ia64io.h b/drivers/input/serio/i8042-x86ia64io.h index 3282b74..5aafe24 100644 --- a/drivers/input/serio/i8042-x86ia64io.h +++ b/drivers/input/serio/i8042-x86ia64io.h @@ -305,7 +305,7 @@ static struct dmi_system_id __initdata i8042_dmi_nomux_table[] = { .ident = "Lenovo 3000 n100", .matches = { DMI_MATCH(DMI_SYS_VENDOR, "LENOVO"), - DMI_MATCH(DMI_PRODUCT_VERSION, "3000 N100"), + DMI_MATCH(DMI_PRODUCT_NAME, "076804U"), }, }, { -- cgit v0.10.2 From 323b8c410a2453f15578c22b0eef50456359bbfc Mon Sep 17 00:00:00 2001 From: Carmelo Amoroso Date: Fri, 5 Sep 2008 14:42:16 +0900 Subject: sh: resume_kernel fix for kernel oops built with CONFIG_BKL_PREEMPT=y. This patch fixes a problem within the SH implementation of resume_kernel code, that implements in assembly the bulk of preempt_schedule_irq function without taking care of the extra code needed to handle the BKL preemptible. The patch basically consists of removing this asm code and calling the common C implementation (see kernel/sched.c) as other archs do. Another change is the missing 'cli' macro invocation at the beginning of the resume_kernel. Signed-off-by: Giuseppe Cavallaro Signed-off-by: Carmelo Amoroso Signed-off-by: Paul Mundt diff --git a/arch/sh/kernel/entry-common.S b/arch/sh/kernel/entry-common.S index 0bc17de..efbb426 100644 --- a/arch/sh/kernel/entry-common.S +++ b/arch/sh/kernel/entry-common.S @@ -92,6 +92,7 @@ ENTRY(ret_from_irq) bra resume_userspace nop ENTRY(resume_kernel) + cli mov.l @(TI_PRE_COUNT,r8), r0 ! current_thread_info->preempt_count tst r0, r0 bf noresched @@ -105,28 +106,9 @@ need_resched: and #0xf0, r0 ! interrupts off (exception path)? cmp/eq #0xf0, r0 bt noresched - - mov.l 1f, r0 - mov.l r0, @(TI_PRE_COUNT,r8) - -#ifdef CONFIG_TRACE_IRQFLAGS mov.l 3f, r0 - jsr @r0 - nop -#endif - sti - mov.l 2f, r0 - jsr @r0 - nop - mov #0, r0 - mov.l r0, @(TI_PRE_COUNT,r8) - cli -#ifdef CONFIG_TRACE_IRQFLAGS - mov.l 4f, r0 - jsr @r0 + jsr @r0 ! call preempt_schedule_irq nop -#endif - bra need_resched nop @@ -137,10 +119,7 @@ noresched: .align 2 1: .long PREEMPT_ACTIVE 2: .long schedule -#ifdef CONFIG_TRACE_IRQFLAGS -3: .long trace_hardirqs_on -4: .long trace_hardirqs_off -#endif +3: .long preempt_schedule_irq #endif ENTRY(resume_userspace) -- cgit v0.10.2 From dbce1f649e3d22aa7ddc0fdbfa6a7470047b61bd Mon Sep 17 00:00:00 2001 From: Paul Mundt Date: Fri, 5 Sep 2008 14:51:28 +0900 Subject: sh64: resume_kernel fix for kernel oops built with CONFIG_BKL_PREEMPT=y. Follows the SH change. Signed-off-by: Paul Mundt diff --git a/arch/sh/kernel/cpu/sh5/entry.S b/arch/sh/kernel/cpu/sh5/entry.S index 04c7da9..e640c63 100644 --- a/arch/sh/kernel/cpu/sh5/entry.S +++ b/arch/sh/kernel/cpu/sh5/entry.S @@ -2,7 +2,7 @@ * arch/sh/kernel/cpu/sh5/entry.S * * Copyright (C) 2000, 2001 Paolo Alberelli - * Copyright (C) 2004 - 2007 Paul Mundt + * Copyright (C) 2004 - 2008 Paul Mundt * Copyright (C) 2003, 2004 Richard Curnow * * This file is subject to the terms and conditions of the GNU General Public @@ -923,6 +923,8 @@ ret_from_exception: blink tr0, ZERO resume_kernel: + CLI() + pta restore_all, tr0 getcon KCR0, r6 @@ -939,19 +941,11 @@ need_resched: andi r7, 0xf0, r7 bne r7, ZERO, tr0 - movi ((PREEMPT_ACTIVE >> 16) & 65535), r8 - shori (PREEMPT_ACTIVE & 65535), r8 - st.l r6, TI_PRE_COUNT, r8 - - STI() - movi schedule, r7 + movi preempt_schedule_irq, r7 ori r7, 1, r7 ptabs r7, tr1 blink tr1, LINK - st.l r6, TI_PRE_COUNT, ZERO - CLI() - pta need_resched, tr1 blink tr1, ZERO #endif -- cgit v0.10.2 From 4eb00c9f92202a759aadbce73ea4a947b639b5e6 Mon Sep 17 00:00:00 2001 From: Magnus Damm Date: Wed, 27 Aug 2008 18:33:56 +0900 Subject: i2c: fix i2c-sh_mobile timing issues This patch teaches the i2c-sh_mobile driver to make use of wait irqs. Without this patch only dte irqs are used which may lead to overruns and cases of missing stop and extra bytes being read on the i2c bus. Use of wait irqs forces the hardware to pause and wait until the cpu is ready. Polling is also reworked in this patch to fix ms delay issues. Verified with bus analyzer and tested on MigoR and AP325RXA boards. Signed-off-by: Magnus Damm Signed-off-by: Paul Mundt diff --git a/drivers/i2c/busses/i2c-sh_mobile.c b/drivers/i2c/busses/i2c-sh_mobile.c index 840e634f..640cbb2 100644 --- a/drivers/i2c/busses/i2c-sh_mobile.c +++ b/drivers/i2c/busses/i2c-sh_mobile.c @@ -31,13 +31,84 @@ #include #include +/* Transmit operation: */ +/* */ +/* 0 byte transmit */ +/* BUS: S A8 ACK P */ +/* IRQ: DTE WAIT */ +/* ICIC: */ +/* ICCR: 0x94 0x90 */ +/* ICDR: A8 */ +/* */ +/* 1 byte transmit */ +/* BUS: S A8 ACK D8(1) ACK P */ +/* IRQ: DTE WAIT WAIT */ +/* ICIC: -DTE */ +/* ICCR: 0x94 0x90 */ +/* ICDR: A8 D8(1) */ +/* */ +/* 2 byte transmit */ +/* BUS: S A8 ACK D8(1) ACK D8(2) ACK P */ +/* IRQ: DTE WAIT WAIT WAIT */ +/* ICIC: -DTE */ +/* ICCR: 0x94 0x90 */ +/* ICDR: A8 D8(1) D8(2) */ +/* */ +/* 3 bytes or more, +---------+ gets repeated */ +/* */ +/* */ +/* Receive operation: */ +/* */ +/* 0 byte receive - not supported since slave may hold SDA low */ +/* */ +/* 1 byte receive [TX] | [RX] */ +/* BUS: S A8 ACK | D8(1) ACK P */ +/* IRQ: DTE WAIT | WAIT DTE */ +/* ICIC: -DTE | +DTE */ +/* ICCR: 0x94 0x81 | 0xc0 */ +/* ICDR: A8 | D8(1) */ +/* */ +/* 2 byte receive [TX]| [RX] */ +/* BUS: S A8 ACK | D8(1) ACK D8(2) ACK P */ +/* IRQ: DTE WAIT | WAIT WAIT DTE */ +/* ICIC: -DTE | +DTE */ +/* ICCR: 0x94 0x81 | 0xc0 */ +/* ICDR: A8 | D8(1) D8(2) */ +/* */ +/* 3 byte receive [TX] | [RX] */ +/* BUS: S A8 ACK | D8(1) ACK D8(2) ACK D8(3) ACK P */ +/* IRQ: DTE WAIT | WAIT WAIT WAIT DTE */ +/* ICIC: -DTE | +DTE */ +/* ICCR: 0x94 0x81 | 0xc0 */ +/* ICDR: A8 | D8(1) D8(2) D8(3) */ +/* */ +/* 4 bytes or more, this part is repeated +---------+ */ +/* */ +/* */ +/* Interrupt order and BUSY flag */ +/* ___ _ */ +/* SDA ___\___XXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXAAAAAAAAA___/ */ +/* SCL \_/1\_/2\_/3\_/4\_/5\_/6\_/7\_/8\___/9\_____/ */ +/* */ +/* S D7 D6 D5 D4 D3 D2 D1 D0 P */ +/* ___ */ +/* WAIT IRQ ________________________________/ \___________ */ +/* TACK IRQ ____________________________________/ \_______ */ +/* DTE IRQ __________________________________________/ \_ */ +/* AL IRQ XXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX */ +/* _______________________________________________ */ +/* BUSY __/ \_ */ +/* */ + enum sh_mobile_i2c_op { OP_START = 0, - OP_TX_ONLY, + OP_TX_FIRST, + OP_TX, OP_TX_STOP, OP_TX_TO_RX, - OP_RX_ONLY, + OP_RX, OP_RX_STOP, + OP_RX_STOP_DATA, }; struct sh_mobile_i2c_data { @@ -127,25 +198,34 @@ static unsigned char i2c_op(struct sh_mobile_i2c_data *pd, spin_lock_irqsave(&pd->lock, flags); switch (op) { - case OP_START: + case OP_START: /* issue start and trigger DTE interrupt */ iowrite8(0x94, ICCR(pd)); break; - case OP_TX_ONLY: + case OP_TX_FIRST: /* disable DTE interrupt and write data */ + iowrite8(ICIC_WAITE | ICIC_ALE | ICIC_TACKE, ICIC(pd)); iowrite8(data, ICDR(pd)); break; - case OP_TX_STOP: + case OP_TX: /* write data */ iowrite8(data, ICDR(pd)); - iowrite8(0x90, ICCR(pd)); - iowrite8(ICIC_ALE | ICIC_TACKE, ICIC(pd)); break; - case OP_TX_TO_RX: + case OP_TX_STOP: /* write data and issue a stop afterwards */ iowrite8(data, ICDR(pd)); + iowrite8(0x90, ICCR(pd)); + break; + case OP_TX_TO_RX: /* select read mode */ iowrite8(0x81, ICCR(pd)); break; - case OP_RX_ONLY: + case OP_RX: /* just read data */ ret = ioread8(ICDR(pd)); break; - case OP_RX_STOP: + case OP_RX_STOP: /* enable DTE interrupt, issue stop */ + iowrite8(ICIC_DTEE | ICIC_WAITE | ICIC_ALE | ICIC_TACKE, + ICIC(pd)); + iowrite8(0xc0, ICCR(pd)); + break; + case OP_RX_STOP_DATA: /* enable DTE interrupt, read data, issue stop */ + iowrite8(ICIC_DTEE | ICIC_WAITE | ICIC_ALE | ICIC_TACKE, + ICIC(pd)); ret = ioread8(ICDR(pd)); iowrite8(0xc0, ICCR(pd)); break; @@ -157,58 +237,120 @@ static unsigned char i2c_op(struct sh_mobile_i2c_data *pd, return ret; } +static int sh_mobile_i2c_is_first_byte(struct sh_mobile_i2c_data *pd) +{ + if (pd->pos == -1) + return 1; + + return 0; +} + +static int sh_mobile_i2c_is_last_byte(struct sh_mobile_i2c_data *pd) +{ + if (pd->pos == (pd->msg->len - 1)) + return 1; + + return 0; +} + +static void sh_mobile_i2c_get_data(struct sh_mobile_i2c_data *pd, + unsigned char *buf) +{ + switch (pd->pos) { + case -1: + *buf = (pd->msg->addr & 0x7f) << 1; + *buf |= (pd->msg->flags & I2C_M_RD) ? 1 : 0; + break; + default: + *buf = pd->msg->buf[pd->pos]; + } +} + +static int sh_mobile_i2c_isr_tx(struct sh_mobile_i2c_data *pd) +{ + unsigned char data; + + if (pd->pos == pd->msg->len) + return 1; + + sh_mobile_i2c_get_data(pd, &data); + + if (sh_mobile_i2c_is_last_byte(pd)) + i2c_op(pd, OP_TX_STOP, data); + else if (sh_mobile_i2c_is_first_byte(pd)) + i2c_op(pd, OP_TX_FIRST, data); + else + i2c_op(pd, OP_TX, data); + + pd->pos++; + return 0; +} + +static int sh_mobile_i2c_isr_rx(struct sh_mobile_i2c_data *pd) +{ + unsigned char data; + int real_pos; + + do { + if (pd->pos <= -1) { + sh_mobile_i2c_get_data(pd, &data); + + if (sh_mobile_i2c_is_first_byte(pd)) + i2c_op(pd, OP_TX_FIRST, data); + else + i2c_op(pd, OP_TX, data); + break; + } + + if (pd->pos == 0) { + i2c_op(pd, OP_TX_TO_RX, 0); + break; + } + + real_pos = pd->pos - 2; + + if (pd->pos == pd->msg->len) { + if (real_pos < 0) { + i2c_op(pd, OP_RX_STOP, 0); + break; + } + data = i2c_op(pd, OP_RX_STOP_DATA, 0); + } else + data = i2c_op(pd, OP_RX, 0); + + pd->msg->buf[real_pos] = data; + } while (0); + + pd->pos++; + return pd->pos == (pd->msg->len + 2); +} + static irqreturn_t sh_mobile_i2c_isr(int irq, void *dev_id) { struct platform_device *dev = dev_id; struct sh_mobile_i2c_data *pd = platform_get_drvdata(dev); - struct i2c_msg *msg = pd->msg; - unsigned char data, sr; - int wakeup = 0; + unsigned char sr; + int wakeup; sr = ioread8(ICSR(pd)); - pd->sr |= sr; + pd->sr |= sr; /* remember state */ dev_dbg(pd->dev, "i2c_isr 0x%02x 0x%02x %s %d %d!\n", sr, pd->sr, - (msg->flags & I2C_M_RD) ? "read" : "write", - pd->pos, msg->len); + (pd->msg->flags & I2C_M_RD) ? "read" : "write", + pd->pos, pd->msg->len); if (sr & (ICSR_AL | ICSR_TACK)) { - iowrite8(0, ICIC(pd)); /* disable interrupts */ - wakeup = 1; - goto do_wakeup; - } + /* don't interrupt transaction - continue to issue stop */ + iowrite8(sr & ~(ICSR_AL | ICSR_TACK), ICSR(pd)); + wakeup = 0; + } else if (pd->msg->flags & I2C_M_RD) + wakeup = sh_mobile_i2c_isr_rx(pd); + else + wakeup = sh_mobile_i2c_isr_tx(pd); - if (pd->pos == msg->len) { - i2c_op(pd, OP_RX_ONLY, 0); - wakeup = 1; - goto do_wakeup; - } + if (sr & ICSR_WAIT) /* TODO: add delay here to support slow acks */ + iowrite8(sr & ~ICSR_WAIT, ICSR(pd)); - if (pd->pos == -1) { - data = (msg->addr & 0x7f) << 1; - data |= (msg->flags & I2C_M_RD) ? 1 : 0; - } else - data = msg->buf[pd->pos]; - - if ((pd->pos == -1) || !(msg->flags & I2C_M_RD)) { - if (msg->flags & I2C_M_RD) - i2c_op(pd, OP_TX_TO_RX, data); - else if (pd->pos == (msg->len - 1)) { - i2c_op(pd, OP_TX_STOP, data); - wakeup = 1; - } else - i2c_op(pd, OP_TX_ONLY, data); - } else { - if (pd->pos == (msg->len - 1)) - data = i2c_op(pd, OP_RX_STOP, 0); - else - data = i2c_op(pd, OP_RX_ONLY, 0); - - msg->buf[pd->pos] = data; - } - pd->pos++; - - do_wakeup: if (wakeup) { pd->sr |= SW_DONE; wake_up(&pd->wait); @@ -219,6 +361,11 @@ static irqreturn_t sh_mobile_i2c_isr(int irq, void *dev_id) static int start_ch(struct sh_mobile_i2c_data *pd, struct i2c_msg *usr_msg) { + if (usr_msg->len == 0 && (usr_msg->flags & I2C_M_RD)) { + dev_err(pd->dev, "Unsupported zero length i2c read\n"); + return -EIO; + } + /* Initialize channel registers */ iowrite8(ioread8(ICCR(pd)) & ~ICCR_ICE, ICCR(pd)); @@ -233,9 +380,8 @@ static int start_ch(struct sh_mobile_i2c_data *pd, struct i2c_msg *usr_msg) pd->pos = -1; pd->sr = 0; - /* Enable all interrupts except wait */ - iowrite8(ioread8(ICIC(pd)) | ICIC_ALE | ICIC_TACKE | ICIC_DTEE, - ICIC(pd)); + /* Enable all interrupts to begin with */ + iowrite8(ICIC_WAITE | ICIC_ALE | ICIC_TACKE | ICIC_DTEE, ICIC(pd)); return 0; } @@ -268,25 +414,18 @@ static int sh_mobile_i2c_xfer(struct i2c_adapter *adapter, if (!k) dev_err(pd->dev, "Transfer request timed out\n"); - retry_count = 10; + retry_count = 1000; again: val = ioread8(ICSR(pd)); dev_dbg(pd->dev, "val 0x%02x pd->sr 0x%02x\n", val, pd->sr); - if ((val | pd->sr) & (ICSR_TACK | ICSR_AL)) { - err = -EIO; - break; - } - /* the interrupt handler may wake us up before the * transfer is finished, so poll the hardware * until we're done. */ - - if (!(!(val & ICSR_BUSY) && (val & ICSR_SCLM) && - (val & ICSR_SDAM))) { - msleep(1); + if (val & ICSR_BUSY) { + udelay(10); if (retry_count--) goto again; @@ -294,6 +433,12 @@ again: dev_err(pd->dev, "Polling timed out\n"); break; } + + /* handle missing acknowledge and arbitration lost */ + if ((val | pd->sr) & (ICSR_TACK | ICSR_AL)) { + err = -EIO; + break; + } } deactivate_ch(pd); -- cgit v0.10.2 From 076c7f4c6c55c37975c8e04ae6827267794d5d2e Mon Sep 17 00:00:00 2001 From: Dmitry Baryshkov Date: Thu, 4 Sep 2008 13:28:33 +0400 Subject: [MTD] [NAND] tmio_nand: fix base address programming Fix offset of second word used for programming base address of memory window. Also program tmio with offset of the FCR, not with physical memory location. Signed-off-by: Dmitry Baryshkov Cc: Ian Molton Signed-off-by: David Woodhouse diff --git a/drivers/mtd/nand/tmio_nand.c b/drivers/mtd/nand/tmio_nand.c index cbab654..edb1e32 100644 --- a/drivers/mtd/nand/tmio_nand.c +++ b/drivers/mtd/nand/tmio_nand.c @@ -109,7 +109,7 @@ struct tmio_nand { void __iomem *ccr; void __iomem *fcr; - unsigned long fcr_phys; + unsigned long fcr_base; unsigned int irq; @@ -316,8 +316,8 @@ static int tmio_hw_init(struct platform_device *dev, struct tmio_nand *tmio) tmio_iowrite8(0x81, tmio->ccr + CCR_ICC); /* (10h)BaseAddress 0x1000 spba.spba2 */ - tmio_iowrite16(tmio->fcr_phys, tmio->ccr + CCR_BASE); - tmio_iowrite16(tmio->fcr_phys >> 16, tmio->ccr + CCR_BASE + 16); + tmio_iowrite16(tmio->fcr_base, tmio->ccr + CCR_BASE); + tmio_iowrite16(tmio->fcr_base >> 16, tmio->ccr + CCR_BASE + 2); /* (04h)Command Register I/O spcmd */ tmio_iowrite8(0x02, tmio->ccr + CCR_COMMAND); @@ -395,7 +395,7 @@ static int tmio_probe(struct platform_device *dev) goto err_iomap_ccr; } - tmio->fcr_phys = (unsigned long)fcr->start; + tmio->fcr_base = fcr->start & 0xfffff; tmio->fcr = ioremap(fcr->start, fcr->end - fcr->start + 1); if (!tmio->fcr) { retval = -EIO; -- cgit v0.10.2 From afbc8d8e72daa5a5faf6a0242186bdfcc42b2427 Mon Sep 17 00:00:00 2001 From: Khem Raj Date: Thu, 4 Sep 2008 23:11:01 -0700 Subject: Fix conditional export of kvh.h and a.out.h to userspace. Some architectures have moved the asm/ into arch/ and some have not. This patch checks for a.out.h and kvh.h in both places before exporting the corresponding file from linux/ [dwmw2: simplified a little] Signed-off-by: Khem Raj Signed-off-by: David Woodhouse diff --git a/include/asm-generic/Kbuild.asm b/include/asm-generic/Kbuild.asm index 1170dc6..1870d5e 100644 --- a/include/asm-generic/Kbuild.asm +++ b/include/asm-generic/Kbuild.asm @@ -1,8 +1,10 @@ -ifneq ($(wildcard $(srctree)/include/asm-$(SRCARCH)/kvm.h),) +ifneq ($(wildcard $(srctree)/arch/$(SRCARCH)/include/asm/kvm.h \ + $(srctree)/include/asm-$(SRCARCH)/kvm.h),) header-y += kvm.h endif -ifneq ($(wildcard $(srctree)/include/asm-$(SRCARCH)/a.out.h),) +ifneq ($(wildcard $(srctree)/arch/$(SRCARCH)/include/asm/a.out.h \ + $(srctree)/include/asm-$(SRCARCH)/a.out.h),) unifdef-y += a.out.h endif unifdef-y += auxvec.h diff --git a/include/linux/Kbuild b/include/linux/Kbuild index 5939125..b68ec09 100644 --- a/include/linux/Kbuild +++ b/include/linux/Kbuild @@ -167,7 +167,8 @@ unifdef-y += acct.h unifdef-y += adb.h unifdef-y += adfs_fs.h unifdef-y += agpgart.h -ifneq ($(wildcard $(srctree)/include/asm-$(SRCARCH)/a.out.h),) +ifneq ($(wildcard $(srctree)/arch/$(SRCARCH)/include/asm/a.out.h \ + $(srctree)/include/asm-$(SRCARCH)/a.out.h),) unifdef-y += a.out.h endif unifdef-y += apm_bios.h @@ -258,7 +259,8 @@ unifdef-y += kd.h unifdef-y += kernelcapi.h unifdef-y += kernel.h unifdef-y += keyboard.h -ifneq ($(wildcard $(srctree)/include/asm-$(SRCARCH)/kvm.h),) +ifneq ($(wildcard $(srctree)/arch/$(SRCARCH)/include/asm/kvm.h \ + $(srctree)/include/asm-$(SRCARCH)/kvm.h),) unifdef-y += kvm.h endif unifdef-y += llc.h -- cgit v0.10.2 From de24125dd0a452bfd4502fc448e3534c5d2e87aa Mon Sep 17 00:00:00 2001 From: Yuri Tikhonov Date: Fri, 5 Sep 2008 08:15:47 -0700 Subject: async_tx: fix the bug in async_tx_run_dependencies Should clear the next pointer of the TX if we are sure that the next TX (say NXT) will be submitted to the channel too. Overwise, we break the chain of descriptors, because we lose the information about the next descriptor to run. So next time, when invoke async_tx_run_dependencies() with TX, it's TX->next will be NULL, and NXT will be never submitted. Cc: [2.6.26] Signed-off-by: Yuri Tikhonov Signed-off-by: Ilya Yanok Signed-off-by: Dan Williams diff --git a/crypto/async_tx/async_tx.c b/crypto/async_tx/async_tx.c index 85eaf7b..e8362c1 100644 --- a/crypto/async_tx/async_tx.c +++ b/crypto/async_tx/async_tx.c @@ -137,7 +137,8 @@ async_tx_run_dependencies(struct dma_async_tx_descriptor *tx) spin_lock_bh(&next->lock); next->parent = NULL; _next = next->next; - next->next = NULL; + if (_next && _next->chan == chan) + next->next = NULL; spin_unlock_bh(&next->lock); next->tx_submit(next); -- cgit v0.10.2 From b35de672e74ceea6482b4f690ad053aec8465c5d Mon Sep 17 00:00:00 2001 From: David Woodhouse Date: Fri, 5 Sep 2008 16:01:15 +0100 Subject: Revert "[ARM] use the new byteorder headers" This reverts commit ae82cbfc8beaa69007aa09966d3983ac938c3577. It needs the new byteorder headers to be exported to userspace, and they aren't yet -- and probably shouldn't be, at this point in the 2.6.27 release cycle (or ever, for that matter). Signed-off-by: David Woodhouse Acked-by: Russell King diff --git a/arch/arm/include/asm/byteorder.h b/arch/arm/include/asm/byteorder.h index d04a7a2..4fbfb22 100644 --- a/arch/arm/include/asm/byteorder.h +++ b/arch/arm/include/asm/byteorder.h @@ -18,15 +18,7 @@ #include #include -#ifdef __ARMEB__ -# define __BIG_ENDIAN -#else -# define __LITTLE_ENDIAN -#endif - -#define __SWAB_64_THRU_32__ - -static inline __attribute_const__ __u32 __arch_swab32(__u32 x) +static inline __attribute_const__ __u32 ___arch__swab32(__u32 x) { __u32 t; @@ -48,8 +40,19 @@ static inline __attribute_const__ __u32 __arch_swab32(__u32 x) return x; } -#define __arch_swab32 __arch_swab32 -#include +#define __arch__swab32(x) ___arch__swab32(x) + +#if !defined(__STRICT_ANSI__) || defined(__KERNEL__) +# define __BYTEORDER_HAS_U64__ +# define __SWAB_64_THRU_32__ +#endif + +#ifdef __ARMEB__ +#include +#else +#include +#endif #endif + -- cgit v0.10.2 From 56c7426b3951e4f35a71d695f1c982989399d6fd Mon Sep 17 00:00:00 2001 From: Peter Zijlstra Date: Mon, 1 Sep 2008 16:44:23 +0200 Subject: sched_clock: fix NOHZ interaction If HLT stops the TSC, we'll fail to account idle time, thereby inflating the actual process times. Fix this by re-calibrating the clock against GTOD when leaving nohz mode. Signed-off-by: Peter Zijlstra Tested-by: Avi Kivity Signed-off-by: Ingo Molnar diff --git a/kernel/time/tick-sched.c b/kernel/time/tick-sched.c index 7a46bde..a87b046 100644 --- a/kernel/time/tick-sched.c +++ b/kernel/time/tick-sched.c @@ -162,6 +162,8 @@ void tick_nohz_stop_idle(int cpu) ts->idle_lastupdate = now; ts->idle_sleeptime = ktime_add(ts->idle_sleeptime, delta); ts->idle_active = 0; + + sched_clock_idle_wakeup_event(0); } } @@ -177,6 +179,7 @@ static ktime_t tick_nohz_start_idle(struct tick_sched *ts) } ts->idle_entrytime = now; ts->idle_active = 1; + sched_clock_idle_sleep_event(); return now; } -- cgit v0.10.2 From 49048622eae698e5c4ae61f7e71200f265ccc529 Mon Sep 17 00:00:00 2001 From: Balbir Singh Date: Fri, 5 Sep 2008 18:12:23 +0200 Subject: sched: fix process time monotonicity Spencer reported a problem where utime and stime were going negative despite the fixes in commit b27f03d4bdc145a09fb7b0c0e004b29f1ee555fa. The suspected reason for the problem is that signal_struct maintains it's own utime and stime (of exited tasks), these are not updated using the new task_utime() routine, hence sig->utime can go backwards and cause the same problem to occur (sig->utime, adds tsk->utime and not task_utime()). This patch fixes the problem TODO: using max(task->prev_utime, derived utime) works for now, but a more generic solution is to implement cputime_max() and use the cputime_gt() function for comparison. Reported-by: spencer@bluehost.com Signed-off-by: Balbir Singh Signed-off-by: Peter Zijlstra Signed-off-by: Ingo Molnar diff --git a/fs/proc/array.c b/fs/proc/array.c index 0d6eb33..71c9be5 100644 --- a/fs/proc/array.c +++ b/fs/proc/array.c @@ -337,65 +337,6 @@ int proc_pid_status(struct seq_file *m, struct pid_namespace *ns, return 0; } -/* - * Use precise platform statistics if available: - */ -#ifdef CONFIG_VIRT_CPU_ACCOUNTING -static cputime_t task_utime(struct task_struct *p) -{ - return p->utime; -} - -static cputime_t task_stime(struct task_struct *p) -{ - return p->stime; -} -#else -static cputime_t task_utime(struct task_struct *p) -{ - clock_t utime = cputime_to_clock_t(p->utime), - total = utime + cputime_to_clock_t(p->stime); - u64 temp; - - /* - * Use CFS's precise accounting: - */ - temp = (u64)nsec_to_clock_t(p->se.sum_exec_runtime); - - if (total) { - temp *= utime; - do_div(temp, total); - } - utime = (clock_t)temp; - - p->prev_utime = max(p->prev_utime, clock_t_to_cputime(utime)); - return p->prev_utime; -} - -static cputime_t task_stime(struct task_struct *p) -{ - clock_t stime; - - /* - * Use CFS's precise accounting. (we subtract utime from - * the total, to make sure the total observed by userspace - * grows monotonically - apps rely on that): - */ - stime = nsec_to_clock_t(p->se.sum_exec_runtime) - - cputime_to_clock_t(task_utime(p)); - - if (stime >= 0) - p->prev_stime = max(p->prev_stime, clock_t_to_cputime(stime)); - - return p->prev_stime; -} -#endif - -static cputime_t task_gtime(struct task_struct *p) -{ - return p->gtime; -} - static int do_task_stat(struct seq_file *m, struct pid_namespace *ns, struct pid *pid, struct task_struct *task, int whole) { diff --git a/include/linux/sched.h b/include/linux/sched.h index cfb0d87..3d9120c 100644 --- a/include/linux/sched.h +++ b/include/linux/sched.h @@ -1475,6 +1475,10 @@ static inline void put_task_struct(struct task_struct *t) __put_task_struct(t); } +extern cputime_t task_utime(struct task_struct *p); +extern cputime_t task_stime(struct task_struct *p); +extern cputime_t task_gtime(struct task_struct *p); + /* * Per process flags */ diff --git a/kernel/exit.c b/kernel/exit.c index 25ed2ad..1639564 100644 --- a/kernel/exit.c +++ b/kernel/exit.c @@ -112,9 +112,9 @@ static void __exit_signal(struct task_struct *tsk) * We won't ever get here for the group leader, since it * will have been the last reference on the signal_struct. */ - sig->utime = cputime_add(sig->utime, tsk->utime); - sig->stime = cputime_add(sig->stime, tsk->stime); - sig->gtime = cputime_add(sig->gtime, tsk->gtime); + sig->utime = cputime_add(sig->utime, task_utime(tsk)); + sig->stime = cputime_add(sig->stime, task_stime(tsk)); + sig->gtime = cputime_add(sig->gtime, task_gtime(tsk)); sig->min_flt += tsk->min_flt; sig->maj_flt += tsk->maj_flt; sig->nvcsw += tsk->nvcsw; diff --git a/kernel/sched.c b/kernel/sched.c index 9a1ddb8..1a5f73c 100644 --- a/kernel/sched.c +++ b/kernel/sched.c @@ -4179,6 +4179,65 @@ void account_steal_time(struct task_struct *p, cputime_t steal) } /* + * Use precise platform statistics if available: + */ +#ifdef CONFIG_VIRT_CPU_ACCOUNTING +cputime_t task_utime(struct task_struct *p) +{ + return p->utime; +} + +cputime_t task_stime(struct task_struct *p) +{ + return p->stime; +} +#else +cputime_t task_utime(struct task_struct *p) +{ + clock_t utime = cputime_to_clock_t(p->utime), + total = utime + cputime_to_clock_t(p->stime); + u64 temp; + + /* + * Use CFS's precise accounting: + */ + temp = (u64)nsec_to_clock_t(p->se.sum_exec_runtime); + + if (total) { + temp *= utime; + do_div(temp, total); + } + utime = (clock_t)temp; + + p->prev_utime = max(p->prev_utime, clock_t_to_cputime(utime)); + return p->prev_utime; +} + +cputime_t task_stime(struct task_struct *p) +{ + clock_t stime; + + /* + * Use CFS's precise accounting. (we subtract utime from + * the total, to make sure the total observed by userspace + * grows monotonically - apps rely on that): + */ + stime = nsec_to_clock_t(p->se.sum_exec_runtime) - + cputime_to_clock_t(task_utime(p)); + + if (stime >= 0) + p->prev_stime = max(p->prev_stime, clock_t_to_cputime(stime)); + + return p->prev_stime; +} +#endif + +inline cputime_t task_gtime(struct task_struct *p) +{ + return p->gtime; +} + +/* * This function gets called by the timer code, with HZ frequency. * We call it with interrupts disabled. * -- cgit v0.10.2 From f171d4d769c8ccac6675892960e37f6485837fae Mon Sep 17 00:00:00 2001 From: Artem Bityutskiy Date: Wed, 3 Sep 2008 16:17:14 +0300 Subject: UBIFS: fix division by zero If fanout is 3, we have division by zero in 'ubifs_read_superblock()': divide error: 0000 [#1] PREEMPT SMP Pid: 28744, comm: mount Not tainted (2.6.27-rc4-ubifs-2.6 #23) EIP: 0060:[] EFLAGS: 00010202 CPU: 0 EIP is at ubifs_reported_space+0x2d/0x69 [ubifs] EAX: 00000000 EBX: 00000000 ECX: 00000000 EDX: 00000000 ESI: 00000000 EDI: f0ae64b0 EBP: f1f9fcf4 ESP: f1f9fce0 DS: 007b ES: 007b FS: 00d8 GS: 0033 SS: 0068 Signed-off-by: Artem Bityutskiy diff --git a/fs/ubifs/budget.c b/fs/ubifs/budget.c index 101d278..73db464 100644 --- a/fs/ubifs/budget.c +++ b/fs/ubifs/budget.c @@ -723,24 +723,25 @@ void ubifs_release_dirty_inode_budget(struct ubifs_info *c, */ long long ubifs_reported_space(const struct ubifs_info *c, uint64_t free) { - int divisor, factor; + int divisor, factor, f; /* * Reported space size is @free * X, where X is UBIFS block size * divided by UBIFS block size + all overhead one data block * introduces. The overhead is the node header + indexing overhead. * - * Indexing overhead is calculations are based on the following - * formula: I = N/(f - 1) + 1, where I - number of indexing nodes, N - - * number of data nodes, f - fanout. Because effective UBIFS fanout is - * twice as less than maximum fanout, we assume that each data node + * Indexing overhead calculations are based on the following formula: + * I = N/(f - 1) + 1, where I - number of indexing nodes, N - number + * of data nodes, f - fanout. Because effective UBIFS fanout is twice + * as less than maximum fanout, we assume that each data node * introduces 3 * @c->max_idx_node_sz / (@c->fanout/2 - 1) bytes. * Note, the multiplier 3 is because UBIFS reseves thrice as more space * for the index. */ + f = c->fanout > 3 ? c->fanout >> 1 : 2; factor = UBIFS_BLOCK_SIZE; divisor = UBIFS_MAX_DATA_NODE_SZ; - divisor += (c->max_idx_node_sz * 3) / ((c->fanout >> 1) - 1); + divisor += (c->max_idx_node_sz * 3) / (f - 1); free *= factor; do_div(free, divisor); return free; -- cgit v0.10.2 From a5cb562d6977d9d7989c346b7b153cef31ec0228 Mon Sep 17 00:00:00 2001 From: Artem Bityutskiy Date: Wed, 3 Sep 2008 18:26:47 +0300 Subject: UBIFS: make minimum fanout 3 UBIFS does not really work correctly when fanout is 2, because of the way we manage the indexing tree. It may just become a list and UBIFS screws up. Signed-off-by: Artem Bityutskiy diff --git a/fs/ubifs/ubifs-media.h b/fs/ubifs/ubifs-media.h index bd2121f..a9ecbd9 100644 --- a/fs/ubifs/ubifs-media.h +++ b/fs/ubifs/ubifs-media.h @@ -87,7 +87,7 @@ #define UBIFS_SK_LEN 8 /* Minimum index tree fanout */ -#define UBIFS_MIN_FANOUT 2 +#define UBIFS_MIN_FANOUT 3 /* Maximum number of levels in UBIFS indexing B-tree */ #define UBIFS_MAX_LEVELS 512 -- cgit v0.10.2 From bf7394ccc13fe291d9258f01113b4c61214ddeae Mon Sep 17 00:00:00 2001 From: Linus Torvalds Date: Fri, 5 Sep 2008 12:38:09 -0700 Subject: Revert "mac80211: Use IWEVASSOCREQIE instead of IWEVCUSTOM" This reverts commit 087d833e5a9f67ba933cb32eaf5a2279c1a5b47c, which was reported to break wireless at least in some combinations with 32bit user space and a 64bit kernel. Alex Williamnson bisected it to this commit. Reported-and-bisected-by: Alex Williamson Acked-by: John W. Linville Cc: David Miller Cc: Jouni Malinen Signed-off-by: Linus Torvalds diff --git a/net/mac80211/mlme.c b/net/mac80211/mlme.c index 9bb68c6..902cac1 100644 --- a/net/mac80211/mlme.c +++ b/net/mac80211/mlme.c @@ -478,21 +478,51 @@ int ieee80211_ht_addt_info_ie_to_ht_bss_info( static void ieee80211_sta_send_associnfo(struct net_device *dev, struct ieee80211_if_sta *ifsta) { + char *buf; + size_t len; + int i; union iwreq_data wrqu; + if (!ifsta->assocreq_ies && !ifsta->assocresp_ies) + return; + + buf = kmalloc(50 + 2 * (ifsta->assocreq_ies_len + + ifsta->assocresp_ies_len), GFP_KERNEL); + if (!buf) + return; + + len = sprintf(buf, "ASSOCINFO("); if (ifsta->assocreq_ies) { - memset(&wrqu, 0, sizeof(wrqu)); - wrqu.data.length = ifsta->assocreq_ies_len; - wireless_send_event(dev, IWEVASSOCREQIE, &wrqu, - ifsta->assocreq_ies); + len += sprintf(buf + len, "ReqIEs="); + for (i = 0; i < ifsta->assocreq_ies_len; i++) { + len += sprintf(buf + len, "%02x", + ifsta->assocreq_ies[i]); + } } - if (ifsta->assocresp_ies) { - memset(&wrqu, 0, sizeof(wrqu)); - wrqu.data.length = ifsta->assocresp_ies_len; - wireless_send_event(dev, IWEVASSOCRESPIE, &wrqu, - ifsta->assocresp_ies); + if (ifsta->assocreq_ies) + len += sprintf(buf + len, " "); + len += sprintf(buf + len, "RespIEs="); + for (i = 0; i < ifsta->assocresp_ies_len; i++) { + len += sprintf(buf + len, "%02x", + ifsta->assocresp_ies[i]); + } + } + len += sprintf(buf + len, ")"); + + if (len > IW_CUSTOM_MAX) { + len = sprintf(buf, "ASSOCRESPIE="); + for (i = 0; i < ifsta->assocresp_ies_len; i++) { + len += sprintf(buf + len, "%02x", + ifsta->assocresp_ies[i]); + } } + + memset(&wrqu, 0, sizeof(wrqu)); + wrqu.data.length = len; + wireless_send_event(dev, IWEVCUSTOM, &wrqu, buf); + + kfree(buf); } -- cgit v0.10.2 From 0510617b85758b6e66f3c602ceccea1826440470 Mon Sep 17 00:00:00 2001 From: Thomas Bogendoerfer Date: Mon, 4 Aug 2008 19:44:34 +0200 Subject: [MIPS] Fix data bus error recovery With -ffunction-section the entries in __dbe_table aren't no longer sorted, so the lookup of exception addresses in do_be() failed for some addresses. To avoid this we now sort __dbe_table. Signed-off-by: Thomas Bogendoerfer Signed-off-by: Ralf Baechle diff --git a/arch/mips/kernel/traps.c b/arch/mips/kernel/traps.c index 426cced..1f579a8 100644 --- a/arch/mips/kernel/traps.c +++ b/arch/mips/kernel/traps.c @@ -373,8 +373,8 @@ void __noreturn die(const char * str, const struct pt_regs * regs) do_exit(SIGSEGV); } -extern const struct exception_table_entry __start___dbe_table[]; -extern const struct exception_table_entry __stop___dbe_table[]; +extern struct exception_table_entry __start___dbe_table[]; +extern struct exception_table_entry __stop___dbe_table[]; __asm__( " .section __dbe_table, \"a\"\n" @@ -1682,4 +1682,6 @@ void __init trap_init(void) flush_icache_range(ebase, ebase + 0x400); flush_tlb_handlers(); + + sort_extable(__start___dbe_table, __stop___dbe_table); } -- cgit v0.10.2 From e0cee3eea7875800451739ae38f99edcf11c133d Mon Sep 17 00:00:00 2001 From: Thomas Bogendoerfer Date: Mon, 4 Aug 2008 20:53:57 +0200 Subject: [MIPS] Fix WARNING: at kernel/smp.c:290 trap_init issues flush_icache_range(), which uses ipi functions to get icache flushing done on all cpus. But this is done before interrupts are enabled and caused WARN_ON messages. This changeset introduces a new local_flush_icache_range() and uses it before interrupts (and additional CPUs) are enabled to avoid this problem. Signed-off-by: Thomas Bogendoerfer Signed-off-by: Ralf Baechle diff --git a/arch/mips/kernel/traps.c b/arch/mips/kernel/traps.c index 1f579a8..6bee290 100644 --- a/arch/mips/kernel/traps.c +++ b/arch/mips/kernel/traps.c @@ -1200,7 +1200,7 @@ void *set_except_vector(int n, void *addr) if (n == 0 && cpu_has_divec) { *(u32 *)(ebase + 0x200) = 0x08000000 | (0x03ffffff & (handler >> 2)); - flush_icache_range(ebase + 0x200, ebase + 0x204); + local_flush_icache_range(ebase + 0x200, ebase + 0x204); } return (void *)old_handler; } @@ -1283,7 +1283,8 @@ static void *set_vi_srs_handler(int n, vi_handler_t addr, int srs) *w = (*w & 0xffff0000) | (((u32)handler >> 16) & 0xffff); w = (u32 *)(b + ori_offset); *w = (*w & 0xffff0000) | ((u32)handler & 0xffff); - flush_icache_range((unsigned long)b, (unsigned long)(b+handler_len)); + local_flush_icache_range((unsigned long)b, + (unsigned long)(b+handler_len)); } else { /* @@ -1295,7 +1296,8 @@ static void *set_vi_srs_handler(int n, vi_handler_t addr, int srs) w = (u32 *)b; *w++ = 0x08000000 | (((u32)handler >> 2) & 0x03fffff); /* j handler */ *w = 0; - flush_icache_range((unsigned long)b, (unsigned long)(b+8)); + local_flush_icache_range((unsigned long)b, + (unsigned long)(b+8)); } return (void *)old_handler; @@ -1515,7 +1517,7 @@ void __cpuinit per_cpu_trap_init(void) void __init set_handler(unsigned long offset, void *addr, unsigned long size) { memcpy((void *)(ebase + offset), addr, size); - flush_icache_range(ebase + offset, ebase + offset + size); + local_flush_icache_range(ebase + offset, ebase + offset + size); } static char panic_null_cerr[] __cpuinitdata = @@ -1680,7 +1682,7 @@ void __init trap_init(void) signal32_init(); #endif - flush_icache_range(ebase, ebase + 0x400); + local_flush_icache_range(ebase, ebase + 0x400); flush_tlb_handlers(); sort_extable(__start___dbe_table, __stop___dbe_table); diff --git a/arch/mips/mm/c-r3k.c b/arch/mips/mm/c-r3k.c index 27a5b46..5500c20 100644 --- a/arch/mips/mm/c-r3k.c +++ b/arch/mips/mm/c-r3k.c @@ -320,6 +320,7 @@ void __cpuinit r3k_cache_init(void) flush_cache_range = r3k_flush_cache_range; flush_cache_page = r3k_flush_cache_page; flush_icache_range = r3k_flush_icache_range; + local_flush_icache_range = r3k_flush_icache_range; flush_cache_sigtramp = r3k_flush_cache_sigtramp; local_flush_data_cache_page = local_r3k_flush_data_cache_page; diff --git a/arch/mips/mm/c-r4k.c b/arch/mips/mm/c-r4k.c index 71df339..6e99665 100644 --- a/arch/mips/mm/c-r4k.c +++ b/arch/mips/mm/c-r4k.c @@ -543,12 +543,8 @@ struct flush_icache_range_args { unsigned long end; }; -static inline void local_r4k_flush_icache_range(void *args) +static inline void local_r4k_flush_icache_range(unsigned long start, unsigned long end) { - struct flush_icache_range_args *fir_args = args; - unsigned long start = fir_args->start; - unsigned long end = fir_args->end; - if (!cpu_has_ic_fills_f_dc) { if (end - start >= dcache_size) { r4k_blast_dcache(); @@ -564,6 +560,15 @@ static inline void local_r4k_flush_icache_range(void *args) protected_blast_icache_range(start, end); } +static inline void local_r4k_flush_icache_range_ipi(void *args) +{ + struct flush_icache_range_args *fir_args = args; + unsigned long start = fir_args->start; + unsigned long end = fir_args->end; + + local_r4k_flush_icache_range(start, end); +} + static void r4k_flush_icache_range(unsigned long start, unsigned long end) { struct flush_icache_range_args args; @@ -571,7 +576,7 @@ static void r4k_flush_icache_range(unsigned long start, unsigned long end) args.start = start; args.end = end; - r4k_on_each_cpu(local_r4k_flush_icache_range, &args, 1); + r4k_on_each_cpu(local_r4k_flush_icache_range_ipi, &args, 1); instruction_hazard(); } @@ -1375,6 +1380,7 @@ void __cpuinit r4k_cache_init(void) local_flush_data_cache_page = local_r4k_flush_data_cache_page; flush_data_cache_page = r4k_flush_data_cache_page; flush_icache_range = r4k_flush_icache_range; + local_flush_icache_range = local_r4k_flush_icache_range; #if defined(CONFIG_DMA_NONCOHERENT) if (coherentio) { diff --git a/arch/mips/mm/c-tx39.c b/arch/mips/mm/c-tx39.c index a9f7f1f..39c8182 100644 --- a/arch/mips/mm/c-tx39.c +++ b/arch/mips/mm/c-tx39.c @@ -362,6 +362,7 @@ void __cpuinit tx39_cache_init(void) flush_cache_range = (void *) tx39h_flush_icache_all; flush_cache_page = (void *) tx39h_flush_icache_all; flush_icache_range = (void *) tx39h_flush_icache_all; + local_flush_icache_range = (void *) tx39h_flush_icache_all; flush_cache_sigtramp = (void *) tx39h_flush_icache_all; local_flush_data_cache_page = (void *) tx39h_flush_icache_all; diff --git a/arch/mips/mm/cache.c b/arch/mips/mm/cache.c index 034e850..1eb7c71 100644 --- a/arch/mips/mm/cache.c +++ b/arch/mips/mm/cache.c @@ -29,6 +29,7 @@ void (*flush_cache_range)(struct vm_area_struct *vma, unsigned long start, void (*flush_cache_page)(struct vm_area_struct *vma, unsigned long page, unsigned long pfn); void (*flush_icache_range)(unsigned long start, unsigned long end); +void (*local_flush_icache_range)(unsigned long start, unsigned long end); void (*__flush_cache_vmap)(void); void (*__flush_cache_vunmap)(void); diff --git a/arch/mips/mm/tlbex.c b/arch/mips/mm/tlbex.c index 76da73a..979cf91 100644 --- a/arch/mips/mm/tlbex.c +++ b/arch/mips/mm/tlbex.c @@ -1273,10 +1273,10 @@ void __cpuinit build_tlb_refill_handler(void) void __cpuinit flush_tlb_handlers(void) { - flush_icache_range((unsigned long)handle_tlbl, + local_flush_icache_range((unsigned long)handle_tlbl, (unsigned long)handle_tlbl + sizeof(handle_tlbl)); - flush_icache_range((unsigned long)handle_tlbs, + local_flush_icache_range((unsigned long)handle_tlbs, (unsigned long)handle_tlbs + sizeof(handle_tlbs)); - flush_icache_range((unsigned long)handle_tlbm, + local_flush_icache_range((unsigned long)handle_tlbm, (unsigned long)handle_tlbm + sizeof(handle_tlbm)); } diff --git a/include/asm-mips/cacheflush.h b/include/asm-mips/cacheflush.h index d5c0f2f..03b1d69 100644 --- a/include/asm-mips/cacheflush.h +++ b/include/asm-mips/cacheflush.h @@ -63,6 +63,7 @@ static inline void flush_icache_page(struct vm_area_struct *vma, } extern void (*flush_icache_range)(unsigned long start, unsigned long end); +extern void (*local_flush_icache_range)(unsigned long start, unsigned long end); extern void (*__flush_cache_vmap)(void); -- cgit v0.10.2 From 073828d078d3e55b23b2b5937a49dc1019c5907d Mon Sep 17 00:00:00 2001 From: Atsushi Nemoto Date: Tue, 26 Aug 2008 21:29:58 +0900 Subject: [MIPS] TXx9: Fix txx9_pcode initialization The txx9_pcode variable was introduced in commit fe1c2bc64f65003b39f331a8e4b0d15b235a4afd ("TXx9: Add 64-bit support") but was not initialized properly. Signed-off-by: Atsushi Nemoto Signed-off-by: Ralf Baechle diff --git a/arch/mips/txx9/generic/setup.c b/arch/mips/txx9/generic/setup.c index 0afe94c..fe6bee0 100644 --- a/arch/mips/txx9/generic/setup.c +++ b/arch/mips/txx9/generic/setup.c @@ -53,6 +53,7 @@ txx9_reg_res_init(unsigned int pcode, unsigned long base, unsigned long size) txx9_ce_res[i].name = txx9_ce_res_name[i]; } + txx9_pcode = pcode; sprintf(txx9_pcode_str, "TX%x", pcode); if (base) { txx9_reg_res.start = base & 0xfffffffffULL; -- cgit v0.10.2 From 3885ec8ca29e5e33e9a5f0ae9dc849d798634ec9 Mon Sep 17 00:00:00 2001 From: Atsushi Nemoto Date: Tue, 26 Aug 2008 22:30:41 +0900 Subject: [MIPS] TX39xx: Add missing local_flush_icache_range initialization Commmit 59e39ecd933ba49eb6efe84cbfa5597a6c9ef18a ("Fix WARNING: at kernel/smp.c:290") introduced local_flush_icache_range but lacks initialization for some TX39 case. Signed-off-by: Atsushi Nemoto Signed-off-by: Ralf Baechle diff --git a/arch/mips/mm/c-tx39.c b/arch/mips/mm/c-tx39.c index 39c8182..f7c8f9c 100644 --- a/arch/mips/mm/c-tx39.c +++ b/arch/mips/mm/c-tx39.c @@ -391,6 +391,7 @@ void __cpuinit tx39_cache_init(void) flush_cache_range = tx39_flush_cache_range; flush_cache_page = tx39_flush_cache_page; flush_icache_range = tx39_flush_icache_range; + local_flush_icache_range = tx39_flush_icache_range; flush_cache_sigtramp = tx39_flush_cache_sigtramp; local_flush_data_cache_page = local_tx39_flush_data_cache_page; -- cgit v0.10.2 From 0011036beeffeada15acd1936d67988de21ca65e Mon Sep 17 00:00:00 2001 From: Atsushi Nemoto Date: Tue, 26 Aug 2008 22:34:57 +0900 Subject: [MIPS] Probe initrd header only if explicitly specified Currently init_initrd() probes initrd header at the last page of kernel image, but it is valid only if addinitrd was used. If addinitrd was not used, the area contains garbage so probing there might misdetect initrd header (magic number is not strictly robust). This patch introduces CONFIG_PROBE_INITRD_HEADER to explicitly enable this probing. Signed-off-by: Atsushi Nemoto Signed-off-by: Ralf Baechle diff --git a/arch/mips/Kconfig b/arch/mips/Kconfig index 4da736e..49896a2 100644 --- a/arch/mips/Kconfig +++ b/arch/mips/Kconfig @@ -1886,6 +1886,15 @@ config STACKTRACE_SUPPORT source "init/Kconfig" +config PROBE_INITRD_HEADER + bool "Probe initrd header created by addinitrd" + depends on BLK_DEV_INITRD + help + Probe initrd header at the last page of kernel image. + Say Y here if you are using arch/mips/boot/addinitrd.c to + add initrd or initramfs image to the kernel image. + Otherwise, say N. + menu "Bus options (PCI, PCMCIA, EISA, ISA, TC)" config HW_HAS_EISA diff --git a/arch/mips/kernel/setup.c b/arch/mips/kernel/setup.c index 2aae76b..16f8edf 100644 --- a/arch/mips/kernel/setup.c +++ b/arch/mips/kernel/setup.c @@ -160,30 +160,33 @@ early_param("rd_size", rd_size_early); static unsigned long __init init_initrd(void) { unsigned long end; - u32 *initrd_header; /* * Board specific code or command line parser should have * already set up initrd_start and initrd_end. In these cases * perfom sanity checks and use them if all looks good. */ - if (initrd_start && initrd_end > initrd_start) - goto sanitize; + if (!initrd_start || initrd_end <= initrd_start) { +#ifdef CONFIG_PROBE_INITRD_HEADER + u32 *initrd_header; - /* - * See if initrd has been added to the kernel image by - * arch/mips/boot/addinitrd.c. In that case a header is - * prepended to initrd and is made up by 8 bytes. The fisrt - * word is a magic number and the second one is the size of - * initrd. Initrd start must be page aligned in any cases. - */ - initrd_header = __va(PAGE_ALIGN(__pa_symbol(&_end) + 8)) - 8; - if (initrd_header[0] != 0x494E5244) + /* + * See if initrd has been added to the kernel image by + * arch/mips/boot/addinitrd.c. In that case a header is + * prepended to initrd and is made up by 8 bytes. The first + * word is a magic number and the second one is the size of + * initrd. Initrd start must be page aligned in any cases. + */ + initrd_header = __va(PAGE_ALIGN(__pa_symbol(&_end) + 8)) - 8; + if (initrd_header[0] != 0x494E5244) + goto disable; + initrd_start = (unsigned long)(initrd_header + 2); + initrd_end = initrd_start + initrd_header[1]; +#else goto disable; - initrd_start = (unsigned long)(initrd_header + 2); - initrd_end = initrd_start + initrd_header[1]; +#endif + } -sanitize: if (initrd_start & ~PAGE_MASK) { pr_err("initrd start must be page aligned\n"); goto disable; -- cgit v0.10.2 From 11d55d2cba6e867be8955e5ae011c54c556b849f Mon Sep 17 00:00:00 2001 From: Li Zefan Date: Fri, 5 Sep 2008 14:00:18 -0700 Subject: res_counter: fix off-by-one bug in setting limit I found we can no longer set limit to 0 with 2.6.27-rcX: # mount -t cgroup -omemory xxx /mnt # mkdir /mnt/0 # echo 0 > /mnt/0/memory.limit_in_bytes bash: echo: write error: Device or resource busy It turned out 'limit' can't be set to 'usage', which is wrong IMO. Signed-off-by: Li Zefan Acked-by: KAMEZAWA Hiroyuki Acked-by: Balbir Singh Acked-by: Pavel Emelyanov Signed-off-by: Andrew Morton Signed-off-by: Linus Torvalds diff --git a/include/linux/res_counter.h b/include/linux/res_counter.h index fdeadd9..271c1c2 100644 --- a/include/linux/res_counter.h +++ b/include/linux/res_counter.h @@ -166,7 +166,7 @@ static inline int res_counter_set_limit(struct res_counter *cnt, int ret = -EBUSY; spin_lock_irqsave(&cnt->lock, flags); - if (cnt->usage < limit) { + if (cnt->usage <= limit) { cnt->limit = limit; ret = 0; } -- cgit v0.10.2 From 3cb5599a84c557c0dd9a19feb63a3788268cf249 Mon Sep 17 00:00:00 2001 From: "Rafael J. Wysocki" Date: Fri, 5 Sep 2008 14:00:19 -0700 Subject: forcedeth: fix kexec regression Fix regression tracked as http://bugzilla.kernel.org/show_bug.cgi?id=11361 and caused by commit f735a2a1a4f2a0f5cd823ce323e82675990469e2 ("[netdrvr] forcedeth: setup wake-on-lan before shutting down") that makes network adapters integrated into the NVidia MCP55 chipsets fail to work in kexeced kernels. The problem appears to be that if the adapter is put into D3_hot during ->shutdown(), it cannot be brought back into D0 after kexec (ref. http://marc.info/?l=linux-kernel&m=121900062814967&w=4). Therefore, only put forcedeth into D3 during ->shutdown() if the system is to be powered off. Signed-off-by: Rafael J. Wysocki Tested-by: Yinghai Lu Cc: Ayaz Abdulla Acked-by: Jeff Garzik Signed-off-by: Andrew Morton Signed-off-by: Linus Torvalds diff --git a/drivers/net/forcedeth.c b/drivers/net/forcedeth.c index 331b86b..0b6ecef 100644 --- a/drivers/net/forcedeth.c +++ b/drivers/net/forcedeth.c @@ -5975,10 +5975,12 @@ static void nv_shutdown(struct pci_dev *pdev) if (netif_running(dev)) nv_close(dev); - pci_enable_wake(pdev, PCI_D3hot, np->wolenabled); - pci_enable_wake(pdev, PCI_D3cold, np->wolenabled); pci_disable_device(pdev); - pci_set_power_state(pdev, PCI_D3hot); + if (system_state == SYSTEM_POWER_OFF) { + if (pci_enable_wake(pdev, PCI_D3cold, np->wolenabled)) + pci_enable_wake(pdev, PCI_D3hot, np->wolenabled); + pci_set_power_state(pdev, PCI_D3hot); + } } #else #define nv_suspend NULL -- cgit v0.10.2 From 34a35bddb9382fc2663e3137875ee58928f7d704 Mon Sep 17 00:00:00 2001 From: Stanislaw Gruszka Date: Fri, 5 Sep 2008 14:00:22 -0700 Subject: atmel_lcdfb: fix oops in rmmod when framebuffer fails to register If framebuffer registration failed in platform driver ->probe() callback, dev_get_drvdata() points to freed memory region, but ->remove() function try to use it and the following oops occurs: Unable to handle kernel NULL pointer dereference at virtual address 00000228 pgd = c3a20000 [00000228] *pgd=23a2b031, *pte=00000000, *ppte=00000000 Internal error: Oops: 17 [#1] Modules linked in: atmel_lcdfb(-) cfbcopyarea cfbimgblt cfbfillrect [last unloaded: atmel_lcdfb] CPU: 0 Not tainted (2.6.27-rc2 #116) PC is at atmel_lcdfb_remove+0x14/0xf8 [atmel_lcdfb] LR is at platform_drv_remove+0x20/0x24 pc : [] lr : [] psr: a0000013 sp : c3a45e84 ip : c3a45ea0 fp : c3a45e9c r10: 00000002 r9 : c3a44000 r8 : c0026c04 r7 : 00000880 r6 : c02bb228 r5 : 00000000 r4 : c02bb230 r3 : bf007e3c r2 : c02bb230 r1 : 00000004 r0 : c02bb228 Flags: NzCv IRQs on FIQs on Mode SVC_32 ISA ARM Segment user Control: 0005317f Table: 23a20000 DAC: 00000015 Process rmmod (pid: 6799, stack limit = 0xc3a44260) Stack: (0xc3a45e84 to 0xc3a46000) 5e80: c02bb230 bf007e3c bf007e3c c3a45eac c3a45ea0 c0157d28 bf006bc0 5ea0: c3a45ec4 c3a45eb0 c0156d20 c0157d18 c02bb230 c02bb2d8 c3a45ee0 c3a45ec8 5ec0: c0156da8 c0156cb8 bf007e3c bf007ee0 c02c8e14 c3a45efc c3a45ee4 c0156018 5ee0: c0156d50 bf007e3c bf007ee0 00000000 c3a45f18 c3a45f00 c0157220 c0155f9c 5f00: 00000000 bf007ee0 bf008000 c3a45f28 c3a45f1c c0157e34 c01571ec c3a45f38 5f20: c3a45f2c bf006ba8 c0157e30 c3a45fa4 c3a45f3c c005772c bf006ba4 656d7461 5f40: 636c5f6c 00626664 c004c988 c3a45f80 c3a45f5c 00000000 c3a45fb0 00000000 5f60: ffffffff becaccd8 00000880 00000000 000a5e80 00000001 bf007ee0 00000880 5f80: c3a45f84 00000000 becaccd4 00000002 000003df 00000081 00000000 c3a45fa8 5fa0: c0026a60 c0057584 00000002 000003df 00900081 000a5e80 00000880 00000000 5fc0: becaccd4 00000002 000003df 00000000 000a5e80 00000001 00000002 0000005f 5fe0: 4004f5ec becacbe8 0001a158 4004f5fc 20000010 00900081 f9ffbadf 7bbfb2bb Backtrace: [] (atmel_lcdfb_remove+0x0/0xf8 [atmel_lcdfb]) from [] (platform_drv_remove+0x20/0x24) r6:bf007e3c r5:bf007e3c r4:c02bb230 [] (platform_drv_remove+0x0/0x24) from [] (__device_release_driver+0x78/0x98) [] (__device_release_driver+0x0/0x98) from [] (driver_detach+0x68/0x90) r5:c02bb2d8 r4:c02bb230 [] (driver_detach+0x0/0x90) from [] (bus_remove_driver+0x8c/0xb4) r6:c02c8e14 r5:bf007ee0 r4:bf007e3c [] (bus_remove_driver+0x0/0xb4) from [] (driver_unregister+0x44/0x48) r6:00000000 r5:bf007ee0 r4:bf007e3c [] (driver_unregister+0x0/0x48) from [] (platform_driver_unregister+0x14/0x18) r6:bf008000 r5:bf007ee0 r4:00000000 [] (platform_driver_unregister+0x0/0x18) from [] (atmel_lcdfb_exit+0x14/0x1c [atmel_lcdfb]) [] (atmel_lcdfb_exit+0x0/0x1c [atmel_lcdfb]) from [] (sys_delete_module+0x1b8/0x22c) [] (sys_delete_module+0x0/0x22c) from [] (ret_fast_syscall+0x0/0x2c) r7:00000081 r6:000003df r5:00000002 r4:becaccd4 Code: e92dd870 e24cb004 e59050c4 e1a06000 (e5954228) ---[ end trace 85476b184d9e68d8 ]--- This patch fixes the oops. Signed-off-by: Stanislaw Gruszka Acked-by: Nicolas Ferre Acked-by: Krzysztof Helt Cc: Haavard Skinnemoen Signed-off-by: Andrew Morton Signed-off-by: Linus Torvalds diff --git a/drivers/video/atmel_lcdfb.c b/drivers/video/atmel_lcdfb.c index 9c59259..5a24c64 100644 --- a/drivers/video/atmel_lcdfb.c +++ b/drivers/video/atmel_lcdfb.c @@ -939,7 +939,7 @@ static int __init atmel_lcdfb_probe(struct platform_device *pdev) ret = register_framebuffer(info); if (ret < 0) { dev_err(dev, "failed to register framebuffer device: %d\n", ret); - goto free_cmap; + goto reset_drvdata; } /* add selected videomode to modelist */ @@ -955,7 +955,8 @@ static int __init atmel_lcdfb_probe(struct platform_device *pdev) return 0; - +reset_drvdata: + dev_set_drvdata(dev, NULL); free_cmap: fb_dealloc_cmap(&info->cmap); unregister_irqs: @@ -992,10 +993,11 @@ static int __exit atmel_lcdfb_remove(struct platform_device *pdev) { struct device *dev = &pdev->dev; struct fb_info *info = dev_get_drvdata(dev); - struct atmel_lcdfb_info *sinfo = info->par; + struct atmel_lcdfb_info *sinfo; - if (!sinfo) + if (!info || !info->par) return 0; + sinfo = info->par; cancel_work_sync(&sinfo->task); exit_backlight(sinfo); -- cgit v0.10.2 From 22f30168d296dbb54a21ebad44c9d735bca6f67b Mon Sep 17 00:00:00 2001 From: Roland McGrath Date: Fri, 5 Sep 2008 14:00:23 -0700 Subject: tracehook: comment pasto fixes Fix some pasto's in comments in the new linux/tracehook.h and asm-generic/syscall.h files. Reported-by: Wenji Huang Signed-off-by: Roland McGrath Signed-off-by: Andrew Morton Signed-off-by: Linus Torvalds diff --git a/include/asm-generic/syscall.h b/include/asm-generic/syscall.h index abcf34c..ea8087b 100644 --- a/include/asm-generic/syscall.h +++ b/include/asm-generic/syscall.h @@ -126,7 +126,7 @@ void syscall_get_arguments(struct task_struct *task, struct pt_regs *regs, * @args: array of argument values to store * * Changes @n arguments to the system call starting with the @i'th argument. - * @n'th argument to @val. Argument @i gets value @args[0], and so on. + * Argument @i gets value @args[0], and so on. * An arch inline version is probably optimal when @i and @n are constants. * * It's only valid to call this when @task is stopped for tracing on diff --git a/include/linux/tracehook.h b/include/linux/tracehook.h index b48d819..6186a78 100644 --- a/include/linux/tracehook.h +++ b/include/linux/tracehook.h @@ -272,7 +272,7 @@ static inline void tracehook_finish_clone(struct task_struct *child, * tracehook_report_clone_complete(). This must prevent the child from * self-reaping if tracehook_report_clone_complete() uses the @child * pointer; otherwise it might have died and been released by the time - * tracehook_report_report_clone_complete() is called. + * tracehook_report_clone_complete() is called. * * Called with no locks held, but the child cannot run until this returns. */ -- cgit v0.10.2 From 70bb08962ea9bd50797ae9f16b2493f5f7c65053 Mon Sep 17 00:00:00 2001 From: Andrew Morton Date: Fri, 5 Sep 2008 14:00:24 -0700 Subject: drivers/mmc/card/block.c: fix refcount leak in mmc_block_open() mmc_block_open() increments md->usage although it returns with -EROFS when default mounting a MMC/SD card with write protect switch on. This reference counting bug prevents /dev/mmcblkX from being released on card removal, and situation worsen with reinsertion until the minor number range runs out. Reported-by: Acked-by: Pierre Ossman Cc: [2.6.25.x, 2.6.26.x] Signed-off-by: Andrew Morton Signed-off-by: Linus Torvalds diff --git a/drivers/mmc/card/block.c b/drivers/mmc/card/block.c index 86dbb36..6986f39 100644 --- a/drivers/mmc/card/block.c +++ b/drivers/mmc/card/block.c @@ -103,8 +103,10 @@ static int mmc_blk_open(struct inode *inode, struct file *filp) check_disk_change(inode->i_bdev); ret = 0; - if ((filp->f_mode & FMODE_WRITE) && md->read_only) + if ((filp->f_mode & FMODE_WRITE) && md->read_only) { + mmc_blk_put(md); ret = -EROFS; + } } return ret; -- cgit v0.10.2 From b74b06c5f6612a72298f37baa65460a59c26ca67 Mon Sep 17 00:00:00 2001 From: "H. Peter Anvin" Date: Fri, 15 Aug 2008 15:36:31 -0700 Subject: x86: boot: stub out unimplemented CPU feature words The CPU feature detection code in the boot code is somewhat minimal, and doesn't include all possible CPUID words. In particular, it doesn't contain the code for CPU feature words 2 (Transmeta), 3 (Linux-specific), 5 (VIA), or 7 (scattered). Zero them out, so we can still set those bits as known at compile time; in particular, this allows creating a Linux-specific NOPL flag and have it required (and therefore resolvable at compile time) in 64-bit mode. Signed-off-by: H. Peter Anvin diff --git a/arch/x86/boot/cpucheck.c b/arch/x86/boot/cpucheck.c index 4b9ae7c..4d3ff03 100644 --- a/arch/x86/boot/cpucheck.c +++ b/arch/x86/boot/cpucheck.c @@ -38,12 +38,12 @@ static const u32 req_flags[NCAPINTS] = { REQUIRED_MASK0, REQUIRED_MASK1, - REQUIRED_MASK2, - REQUIRED_MASK3, + 0, /* REQUIRED_MASK2 not implemented in this file */ + 0, /* REQUIRED_MASK3 not implemented in this file */ REQUIRED_MASK4, - REQUIRED_MASK5, + 0, /* REQUIRED_MASK5 not implemented in this file */ REQUIRED_MASK6, - REQUIRED_MASK7, + 0, /* REQUIRED_MASK7 not implemented in this file */ }; #define A32(a, b, c, d) (((d) << 24)+((c) << 16)+((b) << 8)+(a)) -- cgit v0.10.2 From b6734c35af028f06772c0b2c836c7d579e6d4dad Mon Sep 17 00:00:00 2001 From: "H. Peter Anvin" Date: Mon, 18 Aug 2008 17:39:32 -0700 Subject: x86: add NOPL as a synthetic CPU feature bit The long noops ("NOPL") are supposed to be detected by family >= 6. Unfortunately, several non-Intel x86 implementations, both hardware and software, don't obey this dictum. Instead, probe for NOPL directly by executing a NOPL instruction and see if we get #UD. Signed-off-by: H. Peter Anvin diff --git a/arch/x86/kernel/cpu/common.c b/arch/x86/kernel/cpu/common.c index 80ab20d..0785b3c 100644 --- a/arch/x86/kernel/cpu/common.c +++ b/arch/x86/kernel/cpu/common.c @@ -13,6 +13,7 @@ #include #include #include +#include #ifdef CONFIG_X86_LOCAL_APIC #include #include @@ -341,6 +342,35 @@ static void __init early_cpu_detect(void) early_get_cap(c); } +/* + * The NOPL instruction is supposed to exist on all CPUs with + * family >= 6, unfortunately, that's not true in practice because + * of early VIA chips and (more importantly) broken virtualizers that + * are not easy to detect. Hence, probe for it based on first + * principles. + */ +static void __cpuinit detect_nopl(struct cpuinfo_x86 *c) +{ + const u32 nopl_signature = 0x888c53b1; /* Random number */ + u32 has_nopl = nopl_signature; + + clear_cpu_cap(c, X86_FEATURE_NOPL); + if (c->x86 >= 6) { + asm volatile("\n" + "1: .byte 0x0f,0x1f,0xc0\n" /* nopl %eax */ + "2:\n" + " .section .fixup,\"ax\"\n" + "3: xor %0,%0\n" + " jmp 2b\n" + " .previous\n" + _ASM_EXTABLE(1b,3b) + : "+a" (has_nopl)); + + if (has_nopl == nopl_signature) + set_cpu_cap(c, X86_FEATURE_NOPL); + } +} + static void __cpuinit generic_identify(struct cpuinfo_x86 *c) { u32 tfms, xlvl; @@ -395,8 +425,8 @@ static void __cpuinit generic_identify(struct cpuinfo_x86 *c) } init_scattered_cpuid_features(c); + detect_nopl(c); } - } static void __cpuinit squash_the_stupid_serial_number(struct cpuinfo_x86 *c) diff --git a/arch/x86/kernel/cpu/common_64.c b/arch/x86/kernel/cpu/common_64.c index dd6e3f1..c3afba5 100644 --- a/arch/x86/kernel/cpu/common_64.c +++ b/arch/x86/kernel/cpu/common_64.c @@ -18,6 +18,7 @@ #include #include #include +#include #include #ifdef CONFIG_X86_LOCAL_APIC #include @@ -215,6 +216,39 @@ static void __init early_cpu_support_print(void) } } +/* + * The NOPL instruction is supposed to exist on all CPUs with + * family >= 6, unfortunately, that's not true in practice because + * of early VIA chips and (more importantly) broken virtualizers that + * are not easy to detect. Hence, probe for it based on first + * principles. + * + * Note: no 64-bit chip is known to lack these, but put the code here + * for consistency with 32 bits, and to make it utterly trivial to + * diagnose the problem should it ever surface. + */ +static void __cpuinit detect_nopl(struct cpuinfo_x86 *c) +{ + const u32 nopl_signature = 0x888c53b1; /* Random number */ + u32 has_nopl = nopl_signature; + + clear_cpu_cap(c, X86_FEATURE_NOPL); + if (c->x86 >= 6) { + asm volatile("\n" + "1: .byte 0x0f,0x1f,0xc0\n" /* nopl %eax */ + "2:\n" + " .section .fixup,\"ax\"\n" + "3: xor %0,%0\n" + " jmp 2b\n" + " .previous\n" + _ASM_EXTABLE(1b,3b) + : "+a" (has_nopl)); + + if (has_nopl == nopl_signature) + set_cpu_cap(c, X86_FEATURE_NOPL); + } +} + static void __cpuinit early_identify_cpu(struct cpuinfo_x86 *c); void __init early_cpu_init(void) @@ -313,6 +347,8 @@ static void __cpuinit early_identify_cpu(struct cpuinfo_x86 *c) c->x86_phys_bits = eax & 0xff; } + detect_nopl(c); + if (c->x86_vendor != X86_VENDOR_UNKNOWN && cpu_devs[c->x86_vendor]->c_early_init) cpu_devs[c->x86_vendor]->c_early_init(c); diff --git a/arch/x86/kernel/cpu/feature_names.c b/arch/x86/kernel/cpu/feature_names.c index e43ad4a..c901779 100644 --- a/arch/x86/kernel/cpu/feature_names.c +++ b/arch/x86/kernel/cpu/feature_names.c @@ -39,7 +39,8 @@ const char * const x86_cap_flags[NCAPINTS*32] = { NULL, NULL, NULL, NULL, "constant_tsc", "up", NULL, "arch_perfmon", "pebs", "bts", NULL, NULL, - "rep_good", NULL, NULL, NULL, NULL, NULL, NULL, NULL, + "rep_good", NULL, NULL, NULL, + "nopl", NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, /* Intel-defined (#2) */ diff --git a/include/asm-x86/cpufeature.h b/include/asm-x86/cpufeature.h index 762f6a6..9489283 100644 --- a/include/asm-x86/cpufeature.h +++ b/include/asm-x86/cpufeature.h @@ -72,14 +72,15 @@ #define X86_FEATURE_UP (3*32+ 9) /* smp kernel running on up */ #define X86_FEATURE_FXSAVE_LEAK (3*32+10) /* FXSAVE leaks FOP/FIP/FOP */ #define X86_FEATURE_ARCH_PERFMON (3*32+11) /* Intel Architectural PerfMon */ -#define X86_FEATURE_PEBS (3*32+12) /* Precise-Event Based Sampling */ -#define X86_FEATURE_BTS (3*32+13) /* Branch Trace Store */ -#define X86_FEATURE_SYSCALL32 (3*32+14) /* syscall in ia32 userspace */ -#define X86_FEATURE_SYSENTER32 (3*32+15) /* sysenter in ia32 userspace */ +#define X86_FEATURE_PEBS (3*32+12) /* Precise-Event Based Sampling */ +#define X86_FEATURE_BTS (3*32+13) /* Branch Trace Store */ +#define X86_FEATURE_SYSCALL32 (3*32+14) /* syscall in ia32 userspace */ +#define X86_FEATURE_SYSENTER32 (3*32+15) /* sysenter in ia32 userspace */ #define X86_FEATURE_REP_GOOD (3*32+16) /* rep microcode works well on this CPU */ #define X86_FEATURE_MFENCE_RDTSC (3*32+17) /* Mfence synchronizes RDTSC */ #define X86_FEATURE_LFENCE_RDTSC (3*32+18) /* Lfence synchronizes RDTSC */ -#define X86_FEATURE_11AP (3*32+19) /* Bad local APIC aka 11AP */ +#define X86_FEATURE_11AP (3*32+19) /* Bad local APIC aka 11AP */ +#define X86_FEATURE_NOPL (3*32+20) /* The NOPL (0F 1F) instructions */ /* Intel-defined CPU features, CPUID level 0x00000001 (ecx), word 4 */ #define X86_FEATURE_XMM3 (4*32+ 0) /* Streaming SIMD Extensions-3 */ diff --git a/include/asm-x86/required-features.h b/include/asm-x86/required-features.h index adec887..5c2ff4b 100644 --- a/include/asm-x86/required-features.h +++ b/include/asm-x86/required-features.h @@ -41,6 +41,12 @@ # define NEED_3DNOW 0 #endif +#if defined(CONFIG_X86_P6_NOP) || defined(CONFIG_X86_64) +# define NEED_NOPL (1<<(X86_FEATURE_NOPL & 31)) +#else +# define NEED_NOPL 0 +#endif + #ifdef CONFIG_X86_64 #define NEED_PSE 0 #define NEED_MSR (1<<(X86_FEATURE_MSR & 31)) @@ -67,7 +73,7 @@ #define REQUIRED_MASK1 (NEED_LM|NEED_3DNOW) #define REQUIRED_MASK2 0 -#define REQUIRED_MASK3 0 +#define REQUIRED_MASK3 (NEED_NOPL) #define REQUIRED_MASK4 0 #define REQUIRED_MASK5 0 #define REQUIRED_MASK6 0 -- cgit v0.10.2 From f31d731e4467e61de51d7f6d7115f3b712d9354c Mon Sep 17 00:00:00 2001 From: "H. Peter Anvin" Date: Mon, 18 Aug 2008 17:50:33 -0700 Subject: x86: use X86_FEATURE_NOPL in alternatives Use X86_FEATURE_NOPL to determine if it is safe to use P6 NOPs in alternatives. Also, replace table and loop with simple if statement. Signed-off-by: H. Peter Anvin diff --git a/arch/x86/kernel/alternative.c b/arch/x86/kernel/alternative.c index 2763cb3..65a0c1b 100644 --- a/arch/x86/kernel/alternative.c +++ b/arch/x86/kernel/alternative.c @@ -145,35 +145,25 @@ static const unsigned char *const p6_nops[ASM_NOP_MAX+1] = { extern char __vsyscall_0; const unsigned char *const *find_nop_table(void) { - return boot_cpu_data.x86_vendor != X86_VENDOR_INTEL || - boot_cpu_data.x86 < 6 ? k8_nops : p6_nops; + if (boot_cpu_data.x86_vendor == X86_VENDOR_INTEL && + boot_cpu_has(X86_FEATURE_NOPL)) + return p6_nops; + else + return k8_nops; } #else /* CONFIG_X86_64 */ -static const struct nop { - int cpuid; - const unsigned char *const *noptable; -} noptypes[] = { - { X86_FEATURE_K8, k8_nops }, - { X86_FEATURE_K7, k7_nops }, - { X86_FEATURE_P4, p6_nops }, - { X86_FEATURE_P3, p6_nops }, - { -1, NULL } -}; - const unsigned char *const *find_nop_table(void) { - const unsigned char *const *noptable = intel_nops; - int i; - - for (i = 0; noptypes[i].cpuid >= 0; i++) { - if (boot_cpu_has(noptypes[i].cpuid)) { - noptable = noptypes[i].noptable; - break; - } - } - return noptable; + if (boot_cpu_has(X86_FEATURE_K8)) + return k8_nops; + else if (boot_cpu_has(X86_FEATURE_K7)) + return k7_nops; + else if (boot_cpu_has(X86_FEATURE_NOPL)) + return p6_nops; + else + return intel_nops; } #endif /* CONFIG_X86_64 */ -- cgit v0.10.2 From 8a656496b21efd95fd55b66e0601c5ad41f9b156 Mon Sep 17 00:00:00 2001 From: Takashi Iwai Date: Sat, 6 Sep 2008 11:43:41 +0200 Subject: Fix CONFIG_AC97_BUS dependency CONFIG_AC97_BUS is used from both sound and ucb1400 drivers. The recent change in Kconfig introduced the exclusive dependency on CONFIG_SOUND, and disabled the ucb1400 build without sound. This patch makes CONFIG_AC97_BUS independent. Signed-off-by: Takashi Iwai Tested-by: Randy Dunlap diff --git a/sound/Kconfig b/sound/Kconfig index a37bee0..8ebf512 100644 --- a/sound/Kconfig +++ b/sound/Kconfig @@ -91,6 +91,9 @@ endif # SOUND_PRIME endif # !M68K +endif # SOUND + +# AC97_BUS is used from both sound and ucb1400 config AC97_BUS tristate help @@ -99,4 +102,3 @@ config AC97_BUS sound although they're sharing the AC97 bus. Concerned drivers should "select" this. -endif # SOUND -- cgit v0.10.2 From 1ad77a876da48331451698cc4172c90ab9b6372f Mon Sep 17 00:00:00 2001 From: Lennert Buytenhek Date: Fri, 5 Sep 2008 13:17:11 +0100 Subject: [ARM] 5241/1: provide ioremap_wc() This patch provides an ARM implementation of ioremap_wc(). We use different page table attributes depending on which CPU we are running on: - Non-XScale ARMv5 and earlier systems: The ARMv5 ARM documents four possible mapping types (CB=00/01/10/11). We can't use any of the cached memory types (CB=10/11), since that breaks coherency with peripheral devices. Both CB=00 and CB=01 are suitable for _wc, and CB=01 (Uncached/Buffered) allows the hardware more freedom than CB=00, so we'll use that. (The ARMv5 ARM seems to suggest that CB=01 is allowed to delay stores but isn't allowed to merge them, but there is no other mapping type we can use that allows the hardware to delay and merge stores, so we'll go with CB=01.) - XScale v1/v2 (ARMv5): same as the ARMv5 case above, with the slight difference that on these platforms, CB=01 actually _does_ allow merging stores. (If you want noncoalescing bufferable behavior on Xscale v1/v2, you need to use XCB=101.) - Xscale v3 (ARMv5) and ARMv6+: on these systems, we use TEXCB=00100 mappings (Inner/Outer Uncacheable in xsc3 parlance, Uncached Normal in ARMv6 parlance). The ARMv6 ARM explicitly says that any accesses to Normal memory can be merged, which makes Normal memory more suitable for _wc mappings than Device or Strongly Ordered memory, as the latter two mapping types are guaranteed to maintain transaction number, size and order. We use the Uncached variety of Normal mappings for the same reason that we can't use C=1 mappings on ARMv5. The xsc3 Architecture Specification documents TEXCB=00100 as being Uncacheable and allowing coalescing of writes, which is also just what we need. Signed-off-by: Lennert Buytenhek Signed-off-by: Russell King diff --git a/arch/arm/include/asm/io.h b/arch/arm/include/asm/io.h index 94a95d7..7193485 100644 --- a/arch/arm/include/asm/io.h +++ b/arch/arm/include/asm/io.h @@ -61,8 +61,9 @@ extern void __raw_readsl(const void __iomem *addr, void *data, int longlen); #define MT_DEVICE_NONSHARED 1 #define MT_DEVICE_CACHED 2 #define MT_DEVICE_IXP2000 3 +#define MT_DEVICE_WC 4 /* - * types 4 onwards can be found in asm/mach/map.h and are undefined + * types 5 onwards can be found in asm/mach/map.h and are undefined * for ioremap */ @@ -215,11 +216,13 @@ extern void _memset_io(volatile void __iomem *, int, size_t); #define ioremap(cookie,size) __arm_ioremap(cookie, size, MT_DEVICE) #define ioremap_nocache(cookie,size) __arm_ioremap(cookie, size, MT_DEVICE) #define ioremap_cached(cookie,size) __arm_ioremap(cookie, size, MT_DEVICE_CACHED) +#define ioremap_wc(cookie,size) __arm_ioremap(cookie, size, MT_DEVICE_WC) #define iounmap(cookie) __iounmap(cookie) #else #define ioremap(cookie,size) __arch_ioremap((cookie), (size), MT_DEVICE) #define ioremap_nocache(cookie,size) __arch_ioremap((cookie), (size), MT_DEVICE) #define ioremap_cached(cookie,size) __arch_ioremap((cookie), (size), MT_DEVICE_CACHED) +#define ioremap_wc(cookie,size) __arch_ioremap((cookie), (size), MT_DEVICE_WC) #define iounmap(cookie) __arch_iounmap(cookie) #endif diff --git a/arch/arm/include/asm/mach/map.h b/arch/arm/include/asm/mach/map.h index 06f583b..9eb936e 100644 --- a/arch/arm/include/asm/mach/map.h +++ b/arch/arm/include/asm/mach/map.h @@ -18,13 +18,13 @@ struct map_desc { unsigned int type; }; -/* types 0-3 are defined in asm/io.h */ -#define MT_CACHECLEAN 4 -#define MT_MINICLEAN 5 -#define MT_LOW_VECTORS 6 -#define MT_HIGH_VECTORS 7 -#define MT_MEMORY 8 -#define MT_ROM 9 +/* types 0-4 are defined in asm/io.h */ +#define MT_CACHECLEAN 5 +#define MT_MINICLEAN 6 +#define MT_LOW_VECTORS 7 +#define MT_HIGH_VECTORS 8 +#define MT_MEMORY 9 +#define MT_ROM 10 #define MT_NONSHARED_DEVICE MT_DEVICE_NONSHARED #define MT_IXP2000_DEVICE MT_DEVICE_IXP2000 diff --git a/arch/arm/mm/mmu.c b/arch/arm/mm/mmu.c index 25d9a11..a713e40 100644 --- a/arch/arm/mm/mmu.c +++ b/arch/arm/mm/mmu.c @@ -211,6 +211,12 @@ static struct mem_type mem_types[] = { PMD_SECT_TEX(1), .domain = DOMAIN_IO, }, + [MT_DEVICE_WC] = { /* ioremap_wc */ + .prot_pte = PROT_PTE_DEVICE, + .prot_l1 = PMD_TYPE_TABLE, + .prot_sect = PROT_SECT_DEVICE, + .domain = DOMAIN_IO, + }, [MT_CACHECLEAN] = { .prot_sect = PMD_TYPE_SECT | PMD_SECT_XN, .domain = DOMAIN_KERNEL, @@ -273,6 +279,20 @@ static void __init build_mem_type_table(void) } /* + * On non-Xscale3 ARMv5-and-older systems, use CB=01 + * (Uncached/Buffered) for ioremap_wc() mappings. On XScale3 + * and ARMv6+, use TEXCB=00100 mappings (Inner/Outer Uncacheable + * in xsc3 parlance, Uncached Normal in ARMv6 parlance). + */ + if (cpu_is_xsc3() || cpu_arch >= CPU_ARCH_ARMv6) { + mem_types[MT_DEVICE_WC].prot_pte_ext |= PTE_EXT_TEX(1); + mem_types[MT_DEVICE_WC].prot_sect |= PMD_SECT_TEX(1); + } else { + mem_types[MT_DEVICE_WC].prot_pte |= L_PTE_BUFFERABLE; + mem_types[MT_DEVICE_WC].prot_sect |= PMD_SECT_BUFFERABLE; + } + + /* * ARMv5 and lower, bit 4 must be set for page tables. * (was: cache "update-able on write" bit on ARM610) * However, Xscale cores require this bit to be cleared. -- cgit v0.10.2 From 12cf105cd66d95cf32c73cfa847a50bd1b700f23 Mon Sep 17 00:00:00 2001 From: Krzysztof Helt Date: Thu, 4 Sep 2008 21:09:43 +0200 Subject: x86: delay early cpu initialization until cpuid is done Move early cpu initialization after cpu early get cap so the early cpu initialization can fix up cpu caps. Signed-off-by: Krzysztof Helt Signed-off-by: Yinghai Lu Signed-off-by: Ingo Molnar diff --git a/arch/x86/kernel/cpu/common.c b/arch/x86/kernel/cpu/common.c index 0785b3c..8aab851 100644 --- a/arch/x86/kernel/cpu/common.c +++ b/arch/x86/kernel/cpu/common.c @@ -335,11 +335,11 @@ static void __init early_cpu_detect(void) get_cpu_vendor(c, 1); + early_get_cap(c); + if (c->x86_vendor != X86_VENDOR_UNKNOWN && cpu_devs[c->x86_vendor]->c_early_init) cpu_devs[c->x86_vendor]->c_early_init(c); - - early_get_cap(c); } /* -- cgit v0.10.2 From dd786dd12c99634055a9066f25ea957f29991c22 Mon Sep 17 00:00:00 2001 From: Yinghai Lu Date: Thu, 4 Sep 2008 21:09:43 +0200 Subject: x86: move mtrr cpu cap setting early in early_init_xxxx Krzysztof Helt found MTRR is not detected on k6-2 root cause: we moved mtrr_bp_init() early for mtrr trimming, and in early_detect we only read the CPU capability from cpuid, so some cpu doesn't have that bit in cpuid. So we need to add early_init_xxxx to preset those bit before mtrr_bp_init for those earlier cpus. this patch is for v2.6.27 Reported-by: Krzysztof Helt Signed-off-by: Yinghai Lu Signed-off-by: Ingo Molnar diff --git a/arch/x86/kernel/cpu/amd.c b/arch/x86/kernel/cpu/amd.c index cae9cab..18514ed 100644 --- a/arch/x86/kernel/cpu/amd.c +++ b/arch/x86/kernel/cpu/amd.c @@ -31,6 +31,11 @@ static void __cpuinit early_init_amd(struct cpuinfo_x86 *c) if (c->x86_power & (1<<8)) set_cpu_cap(c, X86_FEATURE_CONSTANT_TSC); } + + /* Set MTRR capability flag if appropriate */ + if (c->x86_model == 13 || c->x86_model == 9 || + (c->x86_model == 8 && c->x86_mask >= 8)) + set_cpu_cap(c, X86_FEATURE_K6_MTRR); } static void __cpuinit init_amd(struct cpuinfo_x86 *c) @@ -166,10 +171,6 @@ static void __cpuinit init_amd(struct cpuinfo_x86 *c) mbytes); } - /* Set MTRR capability flag if appropriate */ - if (c->x86_model == 13 || c->x86_model == 9 || - (c->x86_model == 8 && c->x86_mask >= 8)) - set_cpu_cap(c, X86_FEATURE_K6_MTRR); break; } diff --git a/arch/x86/kernel/cpu/centaur.c b/arch/x86/kernel/cpu/centaur.c index e0f45ed..a0534c0 100644 --- a/arch/x86/kernel/cpu/centaur.c +++ b/arch/x86/kernel/cpu/centaur.c @@ -314,6 +314,16 @@ enum { EAMD3D = 1<<20, }; +static void __cpuinit early_init_centaur(struct cpuinfo_x86 *c) +{ + switch (c->x86) { + case 5: + /* Emulate MTRRs using Centaur's MCR. */ + set_cpu_cap(c, X86_FEATURE_CENTAUR_MCR); + break; + } +} + static void __cpuinit init_centaur(struct cpuinfo_x86 *c) { @@ -462,6 +472,7 @@ centaur_size_cache(struct cpuinfo_x86 *c, unsigned int size) static struct cpu_dev centaur_cpu_dev __cpuinitdata = { .c_vendor = "Centaur", .c_ident = { "CentaurHauls" }, + .c_early_init = early_init_centaur, .c_init = init_centaur, .c_size_cache = centaur_size_cache, }; diff --git a/arch/x86/kernel/cpu/cyrix.c b/arch/x86/kernel/cpu/cyrix.c index e710a21..898a5a2 100644 --- a/arch/x86/kernel/cpu/cyrix.c +++ b/arch/x86/kernel/cpu/cyrix.c @@ -15,13 +15,11 @@ /* * Read NSC/Cyrix DEVID registers (DIR) to get more detailed info. about the CPU */ -static void __cpuinit do_cyrix_devid(unsigned char *dir0, unsigned char *dir1) +static void __cpuinit __do_cyrix_devid(unsigned char *dir0, unsigned char *dir1) { unsigned char ccr2, ccr3; - unsigned long flags; /* we test for DEVID by checking whether CCR3 is writable */ - local_irq_save(flags); ccr3 = getCx86(CX86_CCR3); setCx86(CX86_CCR3, ccr3 ^ 0x80); getCx86(0xc0); /* dummy to change bus */ @@ -44,9 +42,16 @@ static void __cpuinit do_cyrix_devid(unsigned char *dir0, unsigned char *dir1) *dir0 = getCx86(CX86_DIR0); *dir1 = getCx86(CX86_DIR1); } - local_irq_restore(flags); } +static void __cpuinit do_cyrix_devid(unsigned char *dir0, unsigned char *dir1) +{ + unsigned long flags; + + local_irq_save(flags); + __do_cyrix_devid(dir0, dir1); + local_irq_restore(flags); +} /* * Cx86_dir0_msb is a HACK needed by check_cx686_cpuid/slop in bugs.h in * order to identify the Cyrix CPU model after we're out of setup.c @@ -161,6 +166,24 @@ static void __cpuinit geode_configure(void) local_irq_restore(flags); } +static void __cpuinit early_init_cyrix(struct cpuinfo_x86 *c) +{ + unsigned char dir0, dir0_msn, dir1 = 0; + + __do_cyrix_devid(&dir0, &dir1); + dir0_msn = dir0 >> 4; /* identifies CPU "family" */ + + switch (dir0_msn) { + case 3: /* 6x86/6x86L */ + /* Emulate MTRRs using Cyrix's ARRs. */ + set_cpu_cap(c, X86_FEATURE_CYRIX_ARR); + break; + case 5: /* 6x86MX/M II */ + /* Emulate MTRRs using Cyrix's ARRs. */ + set_cpu_cap(c, X86_FEATURE_CYRIX_ARR); + break; + } +} static void __cpuinit init_cyrix(struct cpuinfo_x86 *c) { @@ -416,6 +439,7 @@ static void __cpuinit cyrix_identify(struct cpuinfo_x86 *c) static struct cpu_dev cyrix_cpu_dev __cpuinitdata = { .c_vendor = "Cyrix", .c_ident = { "CyrixInstead" }, + .c_early_init = early_init_cyrix, .c_init = init_cyrix, .c_identify = cyrix_identify, }; -- cgit v0.10.2 From dfb512ec4834116124da61d6c1ee10fd0aa32bd6 Mon Sep 17 00:00:00 2001 From: Max Krasnyansky Date: Fri, 29 Aug 2008 13:11:41 -0700 Subject: sched: arch_reinit_sched_domains() must destroy domains to force rebuild What I realized recently is that calling rebuild_sched_domains() in arch_reinit_sched_domains() by itself is not enough when cpusets are enabled. partition_sched_domains() code is trying to avoid unnecessary domain rebuilds and will not actually rebuild anything if new domain masks match the old ones. What this means is that doing echo 1 > /sys/devices/system/cpu/sched_mc_power_savings on a system with cpusets enabled will not take affect untill something changes in the cpuset setup (ie new sets created or deleted). This patch fixes restore correct behaviour where domains must be rebuilt in order to enable MC powersaving flags. Test on quad-core Core2 box with both CONFIG_CPUSETS and !CONFIG_CPUSETS. Also tested on dual-core Core2 laptop. Lockdep is happy and things are working as expected. Signed-off-by: Max Krasnyansky Tested-by: Vaidyanathan Srinivasan Signed-off-by: Ingo Molnar diff --git a/include/linux/cpuset.h b/include/linux/cpuset.h index e8f450c..2691926 100644 --- a/include/linux/cpuset.h +++ b/include/linux/cpuset.h @@ -160,7 +160,7 @@ static inline int current_cpuset_is_being_rebound(void) static inline void rebuild_sched_domains(void) { - partition_sched_domains(0, NULL, NULL); + partition_sched_domains(1, NULL, NULL); } #endif /* !CONFIG_CPUSETS */ diff --git a/kernel/sched.c b/kernel/sched.c index d601fb0..d72ee9a 100644 --- a/kernel/sched.c +++ b/kernel/sched.c @@ -7589,24 +7589,27 @@ static int dattrs_equal(struct sched_domain_attr *cur, int idx_cur, * and partition_sched_domains() will fallback to the single partition * 'fallback_doms', it also forces the domains to be rebuilt. * + * If doms_new==NULL it will be replaced with cpu_online_map. + * ndoms_new==0 is a special case for destroying existing domains. + * It will not create the default domain. + * * Call with hotplug lock held */ void partition_sched_domains(int ndoms_new, cpumask_t *doms_new, struct sched_domain_attr *dattr_new) { - int i, j; + int i, j, n; mutex_lock(&sched_domains_mutex); /* always unregister in case we don't destroy any domains */ unregister_sched_domain_sysctl(); - if (doms_new == NULL) - ndoms_new = 0; + n = doms_new ? ndoms_new : 0; /* Destroy deleted domains */ for (i = 0; i < ndoms_cur; i++) { - for (j = 0; j < ndoms_new; j++) { + for (j = 0; j < n; j++) { if (cpus_equal(doms_cur[i], doms_new[j]) && dattrs_equal(dattr_cur, i, dattr_new, j)) goto match1; @@ -7619,7 +7622,6 @@ match1: if (doms_new == NULL) { ndoms_cur = 0; - ndoms_new = 1; doms_new = &fallback_doms; cpus_andnot(doms_new[0], cpu_online_map, cpu_isolated_map); dattr_new = NULL; @@ -7656,8 +7658,13 @@ match2: int arch_reinit_sched_domains(void) { get_online_cpus(); + + /* Destroy domains first to force the rebuild */ + partition_sched_domains(0, NULL, NULL); + rebuild_sched_domains(); put_online_cpus(); + return 0; } @@ -7741,7 +7748,7 @@ static int update_sched_domains(struct notifier_block *nfb, case CPU_ONLINE_FROZEN: case CPU_DEAD: case CPU_DEAD_FROZEN: - partition_sched_domains(0, NULL, NULL); + partition_sched_domains(1, NULL, NULL); return NOTIFY_OK; default: -- cgit v0.10.2 From e4a6be4d2850da032a782b5296c07dfdf583af86 Mon Sep 17 00:00:00 2001 From: Eduardo Habkost Date: Thu, 24 Jul 2008 12:15:45 -0300 Subject: x86, xen: Use native_pte_flags instead of native_pte_val for .pte_flags Using native_pte_val triggers the BUG_ON() in the paravirt_ops version of pte_flags(). Signed-off-by: Eduardo Habkost Acked-by: Jeremy Fitzhardinge Signed-off-by: Ingo Molnar diff --git a/arch/x86/xen/enlighten.c b/arch/x86/xen/enlighten.c index 9ff6e3c..a4e201b 100644 --- a/arch/x86/xen/enlighten.c +++ b/arch/x86/xen/enlighten.c @@ -1324,7 +1324,7 @@ static const struct pv_mmu_ops xen_mmu_ops __initdata = { .ptep_modify_prot_commit = __ptep_modify_prot_commit, .pte_val = xen_pte_val, - .pte_flags = native_pte_val, + .pte_flags = native_pte_flags, .pgd_val = xen_pgd_val, .make_pte = xen_make_pte, -- cgit v0.10.2 From d04ec773d7ca1bbc05a2768be95c1cebe2b07757 Mon Sep 17 00:00:00 2001 From: Andreas Herrmann Date: Wed, 6 Aug 2008 10:27:30 +0200 Subject: x86: pda_init(): fix memory leak when using CPU hotplug pda->irqstackptr is allocated whenever a CPU is set online. But it is never freed. This results in a memory leak of 16K for each CPU offline/online cycle. Fix is to allocate pda->irqstackptr only once. Signed-off-by: Andreas Herrmann Cc: akpm@linux-foundation.org Signed-off-by: Ingo Molnar diff --git a/arch/x86/kernel/cpu/common_64.c b/arch/x86/kernel/cpu/common_64.c index c3afba5..4f2eeb56 100644 --- a/arch/x86/kernel/cpu/common_64.c +++ b/arch/x86/kernel/cpu/common_64.c @@ -529,17 +529,20 @@ void pda_init(int cpu) /* others are initialized in smpboot.c */ pda->pcurrent = &init_task; pda->irqstackptr = boot_cpu_stack; + pda->irqstackptr += IRQSTACKSIZE - 64; } else { - pda->irqstackptr = (char *) - __get_free_pages(GFP_ATOMIC, IRQSTACK_ORDER); - if (!pda->irqstackptr) - panic("cannot allocate irqstack for cpu %d", cpu); + if (!pda->irqstackptr) { + pda->irqstackptr = (char *) + __get_free_pages(GFP_ATOMIC, IRQSTACK_ORDER); + if (!pda->irqstackptr) + panic("cannot allocate irqstack for cpu %d", + cpu); + pda->irqstackptr += IRQSTACKSIZE - 64; + } if (pda->nodenumber == 0 && cpu_to_node(cpu) != NUMA_NO_NODE) pda->nodenumber = cpu_to_node(cpu); } - - pda->irqstackptr += IRQSTACKSIZE-64; } char boot_exception_stacks[(N_EXCEPTION_STACKS - 1) * EXCEPTION_STKSZ + -- cgit v0.10.2 From 23952a96ae738277f3139b63d622e22984589031 Mon Sep 17 00:00:00 2001 From: Andreas Herrmann Date: Wed, 6 Aug 2008 10:29:37 +0200 Subject: x86: cpu_init(): fix memory leak when using CPU hotplug Exception stacks are allocated each time a CPU is set online. But the allocated space is never freed. Thus with one CPU hotplug offline/online cycle there is a memory leak of 24K (6 pages) for a CPU. Fix is to allocate exception stacks only once -- when the CPU is set online for the first time. Signed-off-by: Andreas Herrmann Cc: akpm@linux-foundation.org Signed-off-by: Ingo Molnar diff --git a/arch/x86/kernel/cpu/common_64.c b/arch/x86/kernel/cpu/common_64.c index 4f2eeb56..a11f5d4 100644 --- a/arch/x86/kernel/cpu/common_64.c +++ b/arch/x86/kernel/cpu/common_64.c @@ -640,19 +640,22 @@ void __cpuinit cpu_init(void) /* * set up and load the per-CPU TSS */ - for (v = 0; v < N_EXCEPTION_STACKS; v++) { + if (!orig_ist->ist[0]) { static const unsigned int order[N_EXCEPTION_STACKS] = { - [0 ... N_EXCEPTION_STACKS - 1] = EXCEPTION_STACK_ORDER, - [DEBUG_STACK - 1] = DEBUG_STACK_ORDER + [0 ... N_EXCEPTION_STACKS - 1] = EXCEPTION_STACK_ORDER, + [DEBUG_STACK - 1] = DEBUG_STACK_ORDER }; - if (cpu) { - estacks = (char *)__get_free_pages(GFP_ATOMIC, order[v]); - if (!estacks) - panic("Cannot allocate exception stack %ld %d\n", - v, cpu); + for (v = 0; v < N_EXCEPTION_STACKS; v++) { + if (cpu) { + estacks = (char *)__get_free_pages(GFP_ATOMIC, order[v]); + if (!estacks) + panic("Cannot allocate exception " + "stack %ld %d\n", v, cpu); + } + estacks += PAGE_SIZE << order[v]; + orig_ist->ist[v] = t->x86_tss.ist[v] = + (unsigned long)estacks; } - estacks += PAGE_SIZE << order[v]; - orig_ist->ist[v] = t->x86_tss.ist[v] = (unsigned long)estacks; } t->x86_tss.io_bitmap_base = offsetof(struct tss_struct, io_bitmap); -- cgit v0.10.2 From b2e601d14deb2083e2a537b47869ab3895d23a28 Mon Sep 17 00:00:00 2001 From: Andre Detsch Date: Thu, 4 Sep 2008 21:16:27 +0000 Subject: powerpc/spufs: Fix possible scheduling of a context to multiple SPEs We currently have a race when scheduling a context to a SPE - after we have found a runnable context in spusched_tick, the same context may have been scheduled by spu_activate(). This may result in a panic if we try to unschedule a context that has been freed in the meantime. This change exits spu_schedule() if the context has already been scheduled, so we don't end up scheduling it twice. Signed-off-by: Andre Detsch Signed-off-by: Jeremy Kerr diff --git a/arch/powerpc/platforms/cell/spufs/sched.c b/arch/powerpc/platforms/cell/spufs/sched.c index 897c740..67595bc 100644 --- a/arch/powerpc/platforms/cell/spufs/sched.c +++ b/arch/powerpc/platforms/cell/spufs/sched.c @@ -728,7 +728,8 @@ static void spu_schedule(struct spu *spu, struct spu_context *ctx) /* not a candidate for interruptible because it's called either from the scheduler thread or from spu_deactivate */ mutex_lock(&ctx->state_mutex); - __spu_schedule(spu, ctx); + if (ctx->state == SPU_STATE_SAVED) + __spu_schedule(spu, ctx); spu_release(ctx); } -- cgit v0.10.2 From 66bf79182d6531c14c1f9a507b6bbf374a2ae4cd Mon Sep 17 00:00:00 2001 From: Alexey Dobriyan Date: Sun, 7 Sep 2008 18:19:25 -0700 Subject: netfilter: nf_conntrack_sip: de-static helper pointers Helper's ->help hook can run concurrently with itself, so iterating over SIP helpers with static pointer won't work reliably. Signed-off-by: Alexey Dobriyan Signed-off-by: Patrick McHardy Signed-off-by: David S. Miller diff --git a/net/netfilter/nf_conntrack_sip.c b/net/netfilter/nf_conntrack_sip.c index 2f9bbc0..1fa306b 100644 --- a/net/netfilter/nf_conntrack_sip.c +++ b/net/netfilter/nf_conntrack_sip.c @@ -1193,7 +1193,6 @@ static const struct sip_handler sip_handlers[] = { static int process_sip_response(struct sk_buff *skb, const char **dptr, unsigned int *datalen) { - static const struct sip_handler *handler; enum ip_conntrack_info ctinfo; struct nf_conn *ct = nf_ct_get(skb, &ctinfo); unsigned int matchoff, matchlen; @@ -1214,6 +1213,8 @@ static int process_sip_response(struct sk_buff *skb, dataoff = matchoff + matchlen + 1; for (i = 0; i < ARRAY_SIZE(sip_handlers); i++) { + const struct sip_handler *handler; + handler = &sip_handlers[i]; if (handler->response == NULL) continue; @@ -1228,13 +1229,14 @@ static int process_sip_response(struct sk_buff *skb, static int process_sip_request(struct sk_buff *skb, const char **dptr, unsigned int *datalen) { - static const struct sip_handler *handler; enum ip_conntrack_info ctinfo; struct nf_conn *ct = nf_ct_get(skb, &ctinfo); unsigned int matchoff, matchlen; unsigned int cseq, i; for (i = 0; i < ARRAY_SIZE(sip_handlers); i++) { + const struct sip_handler *handler; + handler = &sip_handlers[i]; if (handler->request == NULL) continue; -- cgit v0.10.2 From 887464a41fde7e9e1e11ca86748338033c502446 Mon Sep 17 00:00:00 2001 From: Alexey Dobriyan Date: Sun, 7 Sep 2008 18:20:08 -0700 Subject: netfilter: nf_conntrack_gre: more locking around keymap list gre_keymap_list should be protected in all places. (unless I'm misreading something) Signed-off-by: Alexey Dobriyan Signed-off-by: Patrick McHardy Signed-off-by: David S. Miller diff --git a/net/netfilter/nf_conntrack_proto_gre.c b/net/netfilter/nf_conntrack_proto_gre.c index 654a4f7..b308bb4 100644 --- a/net/netfilter/nf_conntrack_proto_gre.c +++ b/net/netfilter/nf_conntrack_proto_gre.c @@ -97,10 +97,14 @@ int nf_ct_gre_keymap_add(struct nf_conn *ct, enum ip_conntrack_dir dir, kmp = &help->help.ct_pptp_info.keymap[dir]; if (*kmp) { /* check whether it's a retransmission */ + read_lock_bh(&nf_ct_gre_lock); list_for_each_entry(km, &gre_keymap_list, list) { - if (gre_key_cmpfn(km, t) && km == *kmp) + if (gre_key_cmpfn(km, t) && km == *kmp) { + read_unlock_bh(&nf_ct_gre_lock); return 0; + } } + read_unlock_bh(&nf_ct_gre_lock); pr_debug("trying to override keymap_%s for ct %p\n", dir == IP_CT_DIR_REPLY ? "reply" : "orig", ct); return -EEXIST; -- cgit v0.10.2 From 51807e91a76a531d059ec7ce3395c435e4df52a8 Mon Sep 17 00:00:00 2001 From: Alexey Dobriyan Date: Sun, 7 Sep 2008 18:20:36 -0700 Subject: netfilter: nf_conntrack_gre: nf_ct_gre_keymap_flush() fixlet It does "kfree(list_head)" which looks wrong because entity that was allocated is definitely not list_head. However, this all works because list_head is first item in struct nf_ct_gre_keymap. Signed-off-by: Alexey Dobriyan Signed-off-by: Patrick McHardy Signed-off-by: David S. Miller diff --git a/net/netfilter/nf_conntrack_proto_gre.c b/net/netfilter/nf_conntrack_proto_gre.c index b308bb4..9bd0396 100644 --- a/net/netfilter/nf_conntrack_proto_gre.c +++ b/net/netfilter/nf_conntrack_proto_gre.c @@ -45,12 +45,12 @@ static LIST_HEAD(gre_keymap_list); void nf_ct_gre_keymap_flush(void) { - struct list_head *pos, *n; + struct nf_ct_gre_keymap *km, *tmp; write_lock_bh(&nf_ct_gre_lock); - list_for_each_safe(pos, n, &gre_keymap_list) { - list_del(pos); - kfree(pos); + list_for_each_entry_safe(km, tmp, &gre_keymap_list, list) { + list_del(&km->list); + kfree(km); } write_unlock_bh(&nf_ct_gre_lock); } -- cgit v0.10.2 From e3b802ba885b54f4050164c3cfd9e0ba9c73173a Mon Sep 17 00:00:00 2001 From: Patrick McHardy Date: Sun, 7 Sep 2008 18:21:24 -0700 Subject: netfilter: nf_conntrack_irc: make sure string is terminated before calling simple_strtoul Alexey Dobriyan points out: 1. simple_strtoul() silently accepts all characters for given base even if result won't fit into unsigned long. This is amazing stupidity in itself, but 2. nf_conntrack_irc helper use simple_strtoul() for DCC request parsing. Data first copied into 64KB buffer, so theoretically nothing prevents reading past the end of it, since data comes from network given 1). This is not actually a problem currently since we're guaranteed to have a 0 byte in skb_shared_info or in the buffer the data is copied to, but to make this more robust, make sure the string is actually terminated. Signed-off-by: Patrick McHardy Signed-off-by: David S. Miller diff --git a/net/netfilter/nf_conntrack_irc.c b/net/netfilter/nf_conntrack_irc.c index 1b1226d..20633fd 100644 --- a/net/netfilter/nf_conntrack_irc.c +++ b/net/netfilter/nf_conntrack_irc.c @@ -68,11 +68,21 @@ static const char *const dccprotos[] = { static int parse_dcc(char *data, const char *data_end, u_int32_t *ip, u_int16_t *port, char **ad_beg_p, char **ad_end_p) { + char *tmp; + /* at least 12: "AAAAAAAA P\1\n" */ while (*data++ != ' ') if (data > data_end - 12) return -1; + /* Make sure we have a newline character within the packet boundaries + * because simple_strtoul parses until the first invalid character. */ + for (tmp = data; tmp <= data_end; tmp++) + if (*tmp == '\n') + break; + if (tmp > data_end || *tmp != '\n') + return -1; + *ad_beg_p = data; *ip = simple_strtoul(data, &data, 10); -- cgit v0.10.2 From e8a83e10d7dfe5d0841062780769b30f65417e15 Mon Sep 17 00:00:00 2001 From: Jarek Poplawski Date: Sun, 7 Sep 2008 18:41:21 -0700 Subject: pkt_sched: Fix qdisc state in net_tx_action() net_tx_action() can skip __QDISC_STATE_SCHED bit clearing while qdisc is neither ran nor rescheduled, which may cause endless loop in dev_deactivate(). Reported-by: Denys Fedoryshchenko Tested-by: Denys Fedoryshchenko Signed-off-by: Jarek Poplawski Acked-by: Herbert Xu Signed-off-by: David S. Miller diff --git a/net/core/dev.c b/net/core/dev.c index 60c51f7..e719ed2 100644 --- a/net/core/dev.c +++ b/net/core/dev.c @@ -1991,8 +1991,13 @@ static void net_tx_action(struct softirq_action *h) spin_unlock(root_lock); } else { if (!test_bit(__QDISC_STATE_DEACTIVATED, - &q->state)) + &q->state)) { __netif_reschedule(q); + } else { + smp_mb__before_clear_bit(); + clear_bit(__QDISC_STATE_SCHED, + &q->state); + } } } } -- cgit v0.10.2 From f4c4cd6d14e3a3f638475f2f83e26765a7d3327b Mon Sep 17 00:00:00 2001 From: Herbert Xu Date: Mon, 8 Sep 2008 14:29:54 +1000 Subject: Revert "crypto: camellia - Use kernel-provided bitops, unaligned access helpers" This reverts commit bd699f2df6dbc2f4cba528fe598bd63a4d3702c5, which causes camellia to fail the included self-test vectors. It has also been confirmed that it breaks existing encrypted disks using camellia. Signed-off-by: Herbert Xu diff --git a/crypto/camellia.c b/crypto/camellia.c index b1cc4de..493fee7 100644 --- a/crypto/camellia.c +++ b/crypto/camellia.c @@ -35,8 +35,6 @@ #include #include #include -#include -#include static const u32 camellia_sp1110[256] = { 0x70707000,0x82828200,0x2c2c2c00,0xececec00, @@ -337,6 +335,20 @@ static const u32 camellia_sp4404[256] = { /* * macros */ +#define GETU32(v, pt) \ + do { \ + /* latest breed of gcc is clever enough to use move */ \ + memcpy(&(v), (pt), 4); \ + (v) = be32_to_cpu(v); \ + } while(0) + +/* rotation right shift 1byte */ +#define ROR8(x) (((x) >> 8) + ((x) << 24)) +/* rotation left shift 1bit */ +#define ROL1(x) (((x) << 1) + ((x) >> 31)) +/* rotation left shift 1byte */ +#define ROL8(x) (((x) << 8) + ((x) >> 24)) + #define ROLDQ(ll, lr, rl, rr, w0, w1, bits) \ do { \ w0 = ll; \ @@ -371,7 +383,7 @@ static const u32 camellia_sp4404[256] = { ^ camellia_sp3033[(u8)(il >> 8)] \ ^ camellia_sp4404[(u8)(il )]; \ yl ^= yr; \ - yr = ror32(yr, 8); \ + yr = ROR8(yr); \ yr ^= yl; \ } while(0) @@ -393,7 +405,7 @@ static void camellia_setup_tail(u32 *subkey, u32 *subL, u32 *subR, int max) subL[7] ^= subL[1]; subR[7] ^= subR[1]; subL[1] ^= subR[1] & ~subR[9]; dw = subL[1] & subL[9], - subR[1] ^= rol32(dw, 1); /* modified for FLinv(kl2) */ + subR[1] ^= ROL1(dw); /* modified for FLinv(kl2) */ /* round 8 */ subL[11] ^= subL[1]; subR[11] ^= subR[1]; /* round 10 */ @@ -402,7 +414,7 @@ static void camellia_setup_tail(u32 *subkey, u32 *subL, u32 *subR, int max) subL[15] ^= subL[1]; subR[15] ^= subR[1]; subL[1] ^= subR[1] & ~subR[17]; dw = subL[1] & subL[17], - subR[1] ^= rol32(dw, 1); /* modified for FLinv(kl4) */ + subR[1] ^= ROL1(dw); /* modified for FLinv(kl4) */ /* round 14 */ subL[19] ^= subL[1]; subR[19] ^= subR[1]; /* round 16 */ @@ -418,7 +430,7 @@ static void camellia_setup_tail(u32 *subkey, u32 *subL, u32 *subR, int max) } else { subL[1] ^= subR[1] & ~subR[25]; dw = subL[1] & subL[25], - subR[1] ^= rol32(dw, 1); /* modified for FLinv(kl6) */ + subR[1] ^= ROL1(dw); /* modified for FLinv(kl6) */ /* round 20 */ subL[27] ^= subL[1]; subR[27] ^= subR[1]; /* round 22 */ @@ -438,7 +450,7 @@ static void camellia_setup_tail(u32 *subkey, u32 *subL, u32 *subR, int max) subL[26] ^= kw4l; subR[26] ^= kw4r; kw4l ^= kw4r & ~subR[24]; dw = kw4l & subL[24], - kw4r ^= rol32(dw, 1); /* modified for FL(kl5) */ + kw4r ^= ROL1(dw); /* modified for FL(kl5) */ } /* round 17 */ subL[22] ^= kw4l; subR[22] ^= kw4r; @@ -448,7 +460,7 @@ static void camellia_setup_tail(u32 *subkey, u32 *subL, u32 *subR, int max) subL[18] ^= kw4l; subR[18] ^= kw4r; kw4l ^= kw4r & ~subR[16]; dw = kw4l & subL[16], - kw4r ^= rol32(dw, 1); /* modified for FL(kl3) */ + kw4r ^= ROL1(dw); /* modified for FL(kl3) */ /* round 11 */ subL[14] ^= kw4l; subR[14] ^= kw4r; /* round 9 */ @@ -457,7 +469,7 @@ static void camellia_setup_tail(u32 *subkey, u32 *subL, u32 *subR, int max) subL[10] ^= kw4l; subR[10] ^= kw4r; kw4l ^= kw4r & ~subR[8]; dw = kw4l & subL[8], - kw4r ^= rol32(dw, 1); /* modified for FL(kl1) */ + kw4r ^= ROL1(dw); /* modified for FL(kl1) */ /* round 5 */ subL[6] ^= kw4l; subR[6] ^= kw4r; /* round 3 */ @@ -482,7 +494,7 @@ static void camellia_setup_tail(u32 *subkey, u32 *subL, u32 *subR, int max) SUBKEY_R(6) = subR[5] ^ subR[7]; tl = subL[10] ^ (subR[10] & ~subR[8]); dw = tl & subL[8], /* FL(kl1) */ - tr = subR[10] ^ rol32(dw, 1); + tr = subR[10] ^ ROL1(dw); SUBKEY_L(7) = subL[6] ^ tl; /* round 6 */ SUBKEY_R(7) = subR[6] ^ tr; SUBKEY_L(8) = subL[8]; /* FL(kl1) */ @@ -491,7 +503,7 @@ static void camellia_setup_tail(u32 *subkey, u32 *subL, u32 *subR, int max) SUBKEY_R(9) = subR[9]; tl = subL[7] ^ (subR[7] & ~subR[9]); dw = tl & subL[9], /* FLinv(kl2) */ - tr = subR[7] ^ rol32(dw, 1); + tr = subR[7] ^ ROL1(dw); SUBKEY_L(10) = tl ^ subL[11]; /* round 7 */ SUBKEY_R(10) = tr ^ subR[11]; SUBKEY_L(11) = subL[10] ^ subL[12]; /* round 8 */ @@ -504,7 +516,7 @@ static void camellia_setup_tail(u32 *subkey, u32 *subL, u32 *subR, int max) SUBKEY_R(14) = subR[13] ^ subR[15]; tl = subL[18] ^ (subR[18] & ~subR[16]); dw = tl & subL[16], /* FL(kl3) */ - tr = subR[18] ^ rol32(dw, 1); + tr = subR[18] ^ ROL1(dw); SUBKEY_L(15) = subL[14] ^ tl; /* round 12 */ SUBKEY_R(15) = subR[14] ^ tr; SUBKEY_L(16) = subL[16]; /* FL(kl3) */ @@ -513,7 +525,7 @@ static void camellia_setup_tail(u32 *subkey, u32 *subL, u32 *subR, int max) SUBKEY_R(17) = subR[17]; tl = subL[15] ^ (subR[15] & ~subR[17]); dw = tl & subL[17], /* FLinv(kl4) */ - tr = subR[15] ^ rol32(dw, 1); + tr = subR[15] ^ ROL1(dw); SUBKEY_L(18) = tl ^ subL[19]; /* round 13 */ SUBKEY_R(18) = tr ^ subR[19]; SUBKEY_L(19) = subL[18] ^ subL[20]; /* round 14 */ @@ -532,7 +544,7 @@ static void camellia_setup_tail(u32 *subkey, u32 *subL, u32 *subR, int max) } else { tl = subL[26] ^ (subR[26] & ~subR[24]); dw = tl & subL[24], /* FL(kl5) */ - tr = subR[26] ^ rol32(dw, 1); + tr = subR[26] ^ ROL1(dw); SUBKEY_L(23) = subL[22] ^ tl; /* round 18 */ SUBKEY_R(23) = subR[22] ^ tr; SUBKEY_L(24) = subL[24]; /* FL(kl5) */ @@ -541,7 +553,7 @@ static void camellia_setup_tail(u32 *subkey, u32 *subL, u32 *subR, int max) SUBKEY_R(25) = subR[25]; tl = subL[23] ^ (subR[23] & ~subR[25]); dw = tl & subL[25], /* FLinv(kl6) */ - tr = subR[23] ^ rol32(dw, 1); + tr = subR[23] ^ ROL1(dw); SUBKEY_L(26) = tl ^ subL[27]; /* round 19 */ SUBKEY_R(26) = tr ^ subR[27]; SUBKEY_L(27) = subL[26] ^ subL[28]; /* round 20 */ @@ -561,17 +573,17 @@ static void camellia_setup_tail(u32 *subkey, u32 *subL, u32 *subR, int max) /* apply the inverse of the last half of P-function */ i = 2; do { - dw = SUBKEY_L(i + 0) ^ SUBKEY_R(i + 0); dw = rol32(dw, 8);/* round 1 */ + dw = SUBKEY_L(i + 0) ^ SUBKEY_R(i + 0); dw = ROL8(dw);/* round 1 */ SUBKEY_R(i + 0) = SUBKEY_L(i + 0) ^ dw; SUBKEY_L(i + 0) = dw; - dw = SUBKEY_L(i + 1) ^ SUBKEY_R(i + 1); dw = rol32(dw, 8);/* round 2 */ + dw = SUBKEY_L(i + 1) ^ SUBKEY_R(i + 1); dw = ROL8(dw);/* round 2 */ SUBKEY_R(i + 1) = SUBKEY_L(i + 1) ^ dw; SUBKEY_L(i + 1) = dw; - dw = SUBKEY_L(i + 2) ^ SUBKEY_R(i + 2); dw = rol32(dw, 8);/* round 3 */ + dw = SUBKEY_L(i + 2) ^ SUBKEY_R(i + 2); dw = ROL8(dw);/* round 3 */ SUBKEY_R(i + 2) = SUBKEY_L(i + 2) ^ dw; SUBKEY_L(i + 2) = dw; - dw = SUBKEY_L(i + 3) ^ SUBKEY_R(i + 3); dw = rol32(dw, 8);/* round 4 */ + dw = SUBKEY_L(i + 3) ^ SUBKEY_R(i + 3); dw = ROL8(dw);/* round 4 */ SUBKEY_R(i + 3) = SUBKEY_L(i + 3) ^ dw; SUBKEY_L(i + 3) = dw; - dw = SUBKEY_L(i + 4) ^ SUBKEY_R(i + 4); dw = rol32(dw, 9);/* round 5 */ + dw = SUBKEY_L(i + 4) ^ SUBKEY_R(i + 4); dw = ROL8(dw);/* round 5 */ SUBKEY_R(i + 4) = SUBKEY_L(i + 4) ^ dw; SUBKEY_L(i + 4) = dw; - dw = SUBKEY_L(i + 5) ^ SUBKEY_R(i + 5); dw = rol32(dw, 8);/* round 6 */ + dw = SUBKEY_L(i + 5) ^ SUBKEY_R(i + 5); dw = ROL8(dw);/* round 6 */ SUBKEY_R(i + 5) = SUBKEY_L(i + 5) ^ dw; SUBKEY_L(i + 5) = dw; i += 8; } while (i < max); @@ -587,10 +599,10 @@ static void camellia_setup128(const unsigned char *key, u32 *subkey) /** * k == kll || klr || krl || krr (|| is concatenation) */ - kll = get_unaligned_be32(key); - klr = get_unaligned_be32(key + 4); - krl = get_unaligned_be32(key + 8); - krr = get_unaligned_be32(key + 12); + GETU32(kll, key ); + GETU32(klr, key + 4); + GETU32(krl, key + 8); + GETU32(krr, key + 12); /* generate KL dependent subkeys */ /* kw1 */ @@ -695,14 +707,14 @@ static void camellia_setup256(const unsigned char *key, u32 *subkey) * key = (kll || klr || krl || krr || krll || krlr || krrl || krrr) * (|| is concatenation) */ - kll = get_unaligned_be32(key); - klr = get_unaligned_be32(key + 4); - krl = get_unaligned_be32(key + 8); - krr = get_unaligned_be32(key + 12); - krll = get_unaligned_be32(key + 16); - krlr = get_unaligned_be32(key + 20); - krrl = get_unaligned_be32(key + 24); - krrr = get_unaligned_be32(key + 28); + GETU32(kll, key ); + GETU32(klr, key + 4); + GETU32(krl, key + 8); + GETU32(krr, key + 12); + GETU32(krll, key + 16); + GETU32(krlr, key + 20); + GETU32(krrl, key + 24); + GETU32(krrr, key + 28); /* generate KL dependent subkeys */ /* kw1 */ @@ -858,13 +870,13 @@ static void camellia_setup192(const unsigned char *key, u32 *subkey) t0 &= ll; \ t2 |= rr; \ rl ^= t2; \ - lr ^= rol32(t0, 1); \ + lr ^= ROL1(t0); \ t3 = krl; \ t1 = klr; \ t3 &= rl; \ t1 |= lr; \ ll ^= t1; \ - rr ^= rol32(t3, 1); \ + rr ^= ROL1(t3); \ } while(0) #define CAMELLIA_ROUNDSM(xl, xr, kl, kr, yl, yr, il, ir) \ @@ -880,7 +892,7 @@ static void camellia_setup192(const unsigned char *key, u32 *subkey) il ^= kl; \ ir ^= il ^ kr; \ yl ^= ir; \ - yr ^= ror32(il, 8) ^ ir; \ + yr ^= ROR8(il) ^ ir; \ } while(0) /* max = 24: 128bit encrypt, max = 32: 256bit encrypt */ -- cgit v0.10.2 From 4ff23fa93011e2367fea056e72c92709178972d9 Mon Sep 17 00:00:00 2001 From: Hugh Dickins Date: Sun, 7 Sep 2008 00:35:48 +0100 Subject: powerpc: Fix rare boot build breakage MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit A make -j20 powerpc kernel build broke a couple of months ago saying: In file included from arch/powerpc/boot/gunzip_util.h:13, from arch/powerpc/boot/prpmc2800.c:21: arch/powerpc/boot/zlib.h:85: error: expected ‘:’, ‘,’, ‘;’, ‘}’ or ‘__attribute__’ before ‘*’ token arch/powerpc/boot/zlib.h:630: warning: type defaults to ‘int’ in declaration of ‘Byte’ arch/powerpc/boot/zlib.h:630: error: expected ‘;’, ‘,’ or ‘)’ before ‘*’ token It happened again yesterday: too rare for me to confirm the fix, but it looks like the list of dependants on gunzip_util.h was incomplete. Signed-off-by: Hugh Dickins Signed-off-by: Paul Mackerras diff --git a/arch/powerpc/boot/Makefile b/arch/powerpc/boot/Makefile index 14174aa..717a3bc 100644 --- a/arch/powerpc/boot/Makefile +++ b/arch/powerpc/boot/Makefile @@ -49,7 +49,7 @@ zlib := inffast.c inflate.c inftrees.c zlibheader := inffast.h inffixed.h inflate.h inftrees.h infutil.h zliblinuxheader := zlib.h zconf.h zutil.h -$(addprefix $(obj)/,$(zlib) gunzip_util.o main.o): \ +$(addprefix $(obj)/,$(zlib) cuboot-c2k.o gunzip_util.o main.o prpmc2800.o): \ $(addprefix $(obj)/,$(zliblinuxheader)) $(addprefix $(obj)/,$(zlibheader)) src-libfdt := fdt.c fdt_ro.c fdt_wip.c fdt_sw.c fdt_rw.c fdt_strerror.c -- cgit v0.10.2 From 5b66c829bf5c65663b2f68ee6b42f6e834cd39cd Mon Sep 17 00:00:00 2001 From: Alan Cox Date: Wed, 3 Sep 2008 14:48:34 +0100 Subject: ahci, pata_marvell: play nicely together I've been chasing Jeff about this for months. Jeff added the Marvell device identifiers to the ahci driver without making the AHCI driver handle the PATA port. This means a lot of users can't use current kernels and in most distro cases can't even install. This has been going on since March 2008 for the 6121 Marvell, and late 2007 for the 6145!!! This was all pointed out at the time and repeatedly ignored. Bugs assigned to Jeff about this are ignored also. To quote Jeff in email > "Just switch the order of 'ahci' and 'pata_marvell' in > /etc/modprobe.conf, then use Fedora's tools regenerate the initrd. > See? It's not rocket science, and the current configuration can be > easily made to work for Fedora users." (Which isn't trivial, isn't end user, shouldn't be needed, and as it usually breaks at install time is in fact impossible) To quote Jeff in August 2007 > " mv-ahci-pata > Marvell 6121/6141 PATA support. Needs fixing in the 'PATA controller > command' area before it is usable, and can go upstream." Only he add the ids anyway later and caused regressions, adding a further id in March causing more regresions. The actual fix for the moment is very simple. If the user has included the pata_marvell driver let it drive the ports. If they've only selected for SATA support give them the AHCI driver which will run the port a fraction faster. Allow the user to control this decision via ahci.marvell_enable as a module parameter so that distributions can ship 'it works' defaults and smarter users (or config tools) can then flip it over it desired. Signed-off-by: Alan Cox Signed-off-by: Jeff Garzik diff --git a/drivers/ata/Kconfig b/drivers/ata/Kconfig index ae84949..11c8c19 100644 --- a/drivers/ata/Kconfig +++ b/drivers/ata/Kconfig @@ -448,8 +448,10 @@ config PATA_MARVELL tristate "Marvell PATA support via legacy mode" depends on PCI help - This option enables limited support for the Marvell 88SE6145 ATA - controller. + This option enables limited support for the Marvell 88SE61xx ATA + controllers. If you wish to use only the SATA ports then select + the AHCI driver alone. If you wish to the use the PATA port or + both SATA and PATA include this driver. If unsure, say N. diff --git a/drivers/ata/ahci.c b/drivers/ata/ahci.c index c729e69..bce26ee 100644 --- a/drivers/ata/ahci.c +++ b/drivers/ata/ahci.c @@ -610,6 +610,15 @@ module_param(ahci_em_messages, int, 0444); MODULE_PARM_DESC(ahci_em_messages, "Set AHCI Enclosure Management Message type (0 = disabled, 1 = LED"); +#if defined(CONFIG_PATA_MARVELL) || defined(CONFIG_PATA_MARVELL_MODULE) +static int marvell_enable; +#else +static int marvell_enable = 1; +#endif +module_param(marvell_enable, int, 0644); +MODULE_PARM_DESC(marvell_enable, "Marvell SATA via AHCI (1 = enabled)"); + + static inline int ahci_nr_ports(u32 cap) { return (cap & 0x1f) + 1; @@ -732,6 +741,8 @@ static void ahci_save_initial_config(struct pci_dev *pdev, "MV_AHCI HACK: port_map %x -> %x\n", port_map, port_map & mv); + dev_printk(KERN_ERR, &pdev->dev, + "Disabling your PATA port. Use the boot option 'ahci.marvell_enable=0' to avoid this.\n"); port_map &= mv; } @@ -2533,6 +2544,12 @@ static int ahci_init_one(struct pci_dev *pdev, const struct pci_device_id *ent) if (!printed_version++) dev_printk(KERN_DEBUG, &pdev->dev, "version " DRV_VERSION "\n"); + /* The AHCI driver can only drive the SATA ports, the PATA driver + can drive them all so if both drivers are selected make sure + AHCI stays out of the way */ + if (pdev->vendor == PCI_VENDOR_ID_MARVELL && !marvell_enable) + return -ENODEV; + /* acquire resources */ rc = pcim_enable_device(pdev); if (rc) diff --git a/drivers/ata/pata_marvell.c b/drivers/ata/pata_marvell.c index 24a011b..0d87eec 100644 --- a/drivers/ata/pata_marvell.c +++ b/drivers/ata/pata_marvell.c @@ -20,29 +20,30 @@ #include #define DRV_NAME "pata_marvell" -#define DRV_VERSION "0.1.4" +#define DRV_VERSION "0.1.6" /** - * marvell_pre_reset - check for 40/80 pin - * @link: link - * @deadline: deadline jiffies for the operation + * marvell_pata_active - check if PATA is active + * @pdev: PCI device * - * Perform the PATA port setup we need. + * Returns 1 if the PATA port may be active. We know how to check this + * for the 6145 but not the other devices */ -static int marvell_pre_reset(struct ata_link *link, unsigned long deadline) +static int marvell_pata_active(struct pci_dev *pdev) { - struct ata_port *ap = link->ap; - struct pci_dev *pdev = to_pci_dev(ap->host->dev); + int i; u32 devices; void __iomem *barp; - int i; - /* Check if our port is enabled */ + /* We don't yet know how to do this for other devices */ + if (pdev->device != 0x6145) + return 1; barp = pci_iomap(pdev, 5, 0x10); if (barp == NULL) return -ENOMEM; + printk("BAR5:"); for(i = 0; i <= 0x0F; i++) printk("%02X:%02X ", i, ioread8(barp + i)); @@ -51,9 +52,27 @@ static int marvell_pre_reset(struct ata_link *link, unsigned long deadline) devices = ioread32(barp + 0x0C); pci_iounmap(pdev, barp); - if ((pdev->device == 0x6145) && (ap->port_no == 0) && - (!(devices & 0x10))) /* PATA enable ? */ - return -ENOENT; + if (devices & 0x10) + return 1; + return 0; +} + +/** + * marvell_pre_reset - check for 40/80 pin + * @link: link + * @deadline: deadline jiffies for the operation + * + * Perform the PATA port setup we need. + */ + +static int marvell_pre_reset(struct ata_link *link, unsigned long deadline) +{ + struct ata_port *ap = link->ap; + struct pci_dev *pdev = to_pci_dev(ap->host->dev); + + if (pdev->device == 0x6145 && ap->port_no == 0 && + !marvell_pata_active(pdev)) /* PATA enable ? */ + return -ENOENT; return ata_sff_prereset(link, deadline); } @@ -128,6 +147,12 @@ static int marvell_init_one (struct pci_dev *pdev, const struct pci_device_id *i if (pdev->device == 0x6101) ppi[1] = &ata_dummy_port_info; +#if defined(CONFIG_AHCI) || defined(CONFIG_AHCI_MODULE) + if (!marvell_pata_active(pdev)) { + printk(KERN_INFO DRV_NAME ": PATA port not active, deferring to AHCI driver.\n"); + return -ENODEV; + } +#endif return ata_pci_sff_init_one(pdev, ppi, &marvell_sht, NULL); } -- cgit v0.10.2 From 46c5784c8fa736c2bb42fe681189b86e99abdc2e Mon Sep 17 00:00:00 2001 From: Mark Lord Date: Thu, 4 Sep 2008 18:21:07 -0400 Subject: sata_mv: add RocketRaid 1720 PCI ID to driver Signed-off-by: Petr Jelen Signed-off-by: Mark Lord Signed-off-by: Jeff Garzik diff --git a/drivers/ata/sata_mv.c b/drivers/ata/sata_mv.c index 13c1d2a..c815f8e 100644 --- a/drivers/ata/sata_mv.c +++ b/drivers/ata/sata_mv.c @@ -667,7 +667,8 @@ static const struct pci_device_id mv_pci_tbl[] = { { PCI_VDEVICE(MARVELL, 0x5041), chip_504x }, { PCI_VDEVICE(MARVELL, 0x5080), chip_5080 }, { PCI_VDEVICE(MARVELL, 0x5081), chip_508x }, - /* RocketRAID 1740/174x have different identifiers */ + /* RocketRAID 1720/174x have different identifiers */ + { PCI_VDEVICE(TTI, 0x1720), chip_6042 }, { PCI_VDEVICE(TTI, 0x1740), chip_508x }, { PCI_VDEVICE(TTI, 0x1742), chip_508x }, -- cgit v0.10.2 From 17248461cb66103b87ff03bdee34aa61035cc93e Mon Sep 17 00:00:00 2001 From: Tejun Heo Date: Fri, 29 Aug 2008 16:03:59 +0200 Subject: ahci: disable PMP for marvell ahcis Marvell ahcis don't play nicely with PMPs. Disable it. Reported by KueiHuan Chen in the following thread. http://thread.gmane.org/gmane.linux.ide/33296 Signed-off-by: Tejun Heo Cc: KueiHuan Chen Cc: Mark Lord Signed-off-by: Jeff Garzik diff --git a/drivers/ata/ahci.c b/drivers/ata/ahci.c index bce26ee..66aa146 100644 --- a/drivers/ata/ahci.c +++ b/drivers/ata/ahci.c @@ -420,7 +420,7 @@ static const struct ata_port_info ahci_port_info[] = { /* board_ahci_mv */ { AHCI_HFLAGS (AHCI_HFLAG_NO_NCQ | AHCI_HFLAG_NO_MSI | - AHCI_HFLAG_MV_PATA), + AHCI_HFLAG_MV_PATA | AHCI_HFLAG_NO_PMP), .flags = ATA_FLAG_SATA | ATA_FLAG_NO_LEGACY | ATA_FLAG_MMIO | ATA_FLAG_PIO_DMA, .pio_mask = 0x1f, /* pio0-4 */ -- cgit v0.10.2 From 2fd673ecf0378ddeeeb87b3605e50212e0c0ddc6 Mon Sep 17 00:00:00 2001 From: Tejun Heo Date: Fri, 29 Aug 2008 16:13:12 +0200 Subject: sata_nv: disable hardreset for generic of them being unifying probing, hotplug and EH reset paths uniform. Previously, broken hardreset could go unnoticed as it wasn't used during probing but when something goes wrong or after hotplug the problem will surface and bite hard. OSDL bug 11195 reports that sata_nv generic flavor falls into this category. Hardreset itself succeeds but PHY stays offline after hardreset. I tried longer debounce timing but the result was the same. http://bugzilla.kernel.org/show_bug.cgi?id=11195 So, it seems we'll have to drop hardreset from the generic flavor. Signed-off-by: Tejun Heo Cc: Peer Chen Signed-off-by: Jeff Garzik diff --git a/drivers/ata/sata_nv.c b/drivers/ata/sata_nv.c index 858f706..1e1f3f3 100644 --- a/drivers/ata/sata_nv.c +++ b/drivers/ata/sata_nv.c @@ -309,8 +309,6 @@ static void nv_nf2_freeze(struct ata_port *ap); static void nv_nf2_thaw(struct ata_port *ap); static void nv_ck804_freeze(struct ata_port *ap); static void nv_ck804_thaw(struct ata_port *ap); -static int nv_hardreset(struct ata_link *link, unsigned int *class, - unsigned long deadline); static int nv_adma_slave_config(struct scsi_device *sdev); static int nv_adma_check_atapi_dma(struct ata_queued_cmd *qc); static void nv_adma_qc_prep(struct ata_queued_cmd *qc); @@ -407,7 +405,7 @@ static struct scsi_host_template nv_swncq_sht = { static struct ata_port_operations nv_generic_ops = { .inherits = &ata_bmdma_port_ops, - .hardreset = nv_hardreset, + .hardreset = ATA_OP_NULL, .scr_read = nv_scr_read, .scr_write = nv_scr_write, }; @@ -1588,21 +1586,6 @@ static void nv_mcp55_thaw(struct ata_port *ap) ata_sff_thaw(ap); } -static int nv_hardreset(struct ata_link *link, unsigned int *class, - unsigned long deadline) -{ - int rc; - - /* SATA hardreset fails to retrieve proper device signature on - * some controllers. Request follow up SRST. For more info, - * see http://bugzilla.kernel.org/show_bug.cgi?id=3352 - */ - rc = sata_sff_hardreset(link, class, deadline); - if (rc) - return rc; - return -EAGAIN; -} - static void nv_adma_error_handler(struct ata_port *ap) { struct nv_adma_port_priv *pp = ap->private_data; -- cgit v0.10.2 From 9c2676b61a5a4b6d99e65fb2f438fb3914302eda Mon Sep 17 00:00:00 2001 From: Tejun Heo Date: Fri, 29 Aug 2008 16:27:43 +0200 Subject: libata-sff: kill spurious WARN_ON() in ata_hsm_move() On HSM_ST_ERR, ata_hsm_move() triggers WARN_ON() if AC_ERR_DEV or AC_ERR_HSM is not set. PHY events may trigger HSM_ST_ERR with other error codes and, with or without it, there just isn't much reason to do WARN_ON() on it. Even if error code is not set there, core EH logic won't have any problem dealing with the error condition. OSDL bz#11065 reports this problem. Signed-off-by: Tejun Heo Signed-off-by: Jeff Garzik diff --git a/drivers/ata/libata-sff.c b/drivers/ata/libata-sff.c index 304fdc6..2a4c516 100644 --- a/drivers/ata/libata-sff.c +++ b/drivers/ata/libata-sff.c @@ -1315,11 +1315,6 @@ fsm_start: break; case HSM_ST_ERR: - /* make sure qc->err_mask is available to - * know what's wrong and recover - */ - WARN_ON(!(qc->err_mask & (AC_ERR_DEV | AC_ERR_HSM))); - ap->hsm_task_state = HSM_ST_IDLE; /* complete taskfile transaction */ -- cgit v0.10.2 From de058cdea65842ed4bf17da6b50d6fe6b120a6ef Mon Sep 17 00:00:00 2001 From: David Milburn Date: Fri, 29 Aug 2008 10:36:28 -0500 Subject: pata_sil680: remove duplicate pcim_enable_device Remove duplicate call to pcim_enable_device in sil680_init_one. Signed-off-by: David Milburn Signed-off-by: Jeff Garzik diff --git a/drivers/ata/pata_sil680.c b/drivers/ata/pata_sil680.c index 720b864..e970b22 100644 --- a/drivers/ata/pata_sil680.c +++ b/drivers/ata/pata_sil680.c @@ -322,9 +322,6 @@ static int __devinit sil680_init_one(struct pci_dev *pdev, /* Try to acquire MMIO resources and fallback to PIO if * that fails */ - rc = pcim_enable_device(pdev); - if (rc) - return rc; rc = pcim_iomap_regions(pdev, 1 << SIL680_MMIO_BAR, DRV_NAME); if (rc) goto use_ioports; -- cgit v0.10.2 From 8e48b6b307085ce8a747cf94294742f7b7a11b18 Mon Sep 17 00:00:00 2001 From: Seth Heasley Date: Wed, 27 Aug 2008 16:47:22 -0700 Subject: ahci: RAID mode SATA patch for Intel Ibex Peak DeviceIDs Add the Intel Ibex Peak (PCH) SATA RAID Controller DeviceIDs. Signed-off-by: Seth Heasley Signed-off-by: Jeff Garzik diff --git a/drivers/ata/ahci.c b/drivers/ata/ahci.c index 66aa146..2e1a7cb 100644 --- a/drivers/ata/ahci.c +++ b/drivers/ata/ahci.c @@ -487,7 +487,9 @@ static const struct pci_device_id ahci_pci_tbl[] = { { PCI_VDEVICE(INTEL, 0x3a05), board_ahci }, /* ICH10 */ { PCI_VDEVICE(INTEL, 0x3a25), board_ahci }, /* ICH10 */ { PCI_VDEVICE(INTEL, 0x3b24), board_ahci }, /* PCH RAID */ + { PCI_VDEVICE(INTEL, 0x3b25), board_ahci }, /* PCH RAID */ { PCI_VDEVICE(INTEL, 0x3b2b), board_ahci }, /* PCH RAID */ + { PCI_VDEVICE(INTEL, 0x3b2c), board_ahci }, /* PCH RAID */ /* JMicron 360/1/3/5/6, match class to avoid IDE function */ { PCI_VENDOR_ID_JMICRON, PCI_ANY_ID, PCI_ANY_ID, PCI_ANY_ID, -- cgit v0.10.2 From 4a911b1efe219fa3c8af697be0054c72e13bdae4 Mon Sep 17 00:00:00 2001 From: Thomas Bogendoerfer Date: Thu, 4 Sep 2008 23:05:45 +0200 Subject: [MIPS] IP22: Fix detection of second HPC3 on Challenge S The second HPC3 could be found only on Guiness systems (Challenge-S), but not on fullhouse (Indigo2) systems. Signed-off-by: Thomas Bogendoerfer Signed-off-by: Ralf Baechle diff --git a/arch/mips/sgi-ip22/ip22-platform.c b/arch/mips/sgi-ip22/ip22-platform.c index 6014123..52486c4d 100644 --- a/arch/mips/sgi-ip22/ip22-platform.c +++ b/arch/mips/sgi-ip22/ip22-platform.c @@ -150,7 +150,7 @@ static int __init sgiseeq_devinit(void) return res; /* Second HPC is missing? */ - if (!ip22_is_fullhouse() || + if (ip22_is_fullhouse() || get_dbe(tmp, (unsigned int *)&hpc3c1->pbdma[1])) return 0; -- cgit v0.10.2 From 0253398ca1df7e1d2bfbb452175c964a0862482c Mon Sep 17 00:00:00 2001 From: Jeremy Fitzhardinge Date: Mon, 8 Sep 2008 09:54:49 -0700 Subject: xen: fix 2.6.27-rc5 xen balloon driver warnings Set the class so it doesn't clash with the normal memory class. Signed-off-by: Jeremy Fitzhardinge Signed-off-by: Ingo Molnar =================================================================== diff --git a/drivers/xen/balloon.c b/drivers/xen/balloon.c index d4427cb..2e15da54 100644 --- a/drivers/xen/balloon.c +++ b/drivers/xen/balloon.c @@ -60,7 +60,7 @@ #define PAGES2KB(_p) ((_p)<<(PAGE_SHIFT-10)) -#define BALLOON_CLASS_NAME "memory" +#define BALLOON_CLASS_NAME "xen_memory" struct balloon_stats { /* We aim for 'current allocation' == 'target allocation'. */ -- cgit v0.10.2 From 14469a8dd23677921db5e7354a602c98d9c6300f Mon Sep 17 00:00:00 2001 From: Linus Torvalds Date: Fri, 5 Sep 2008 09:30:14 -0700 Subject: x86: disable static NOPLs on 32 bits On 32-bit, at least the generic nops are fairly reasonable, but the default nops for 64-bit really look pretty sad, and the P6 nops really do look better. So I would suggest perhaps moving the static P6 nop selection into the CONFIG_X86_64 thing. The alternative is to just get rid of that static nop selection, and just have two cases: 32-bit and 64-bit, and just pick obviously safe cases for them. Signed-off-by: H. Peter Anvin diff --git a/arch/x86/Kconfig.cpu b/arch/x86/Kconfig.cpu index 2c518fb..b225219 100644 --- a/arch/x86/Kconfig.cpu +++ b/arch/x86/Kconfig.cpu @@ -382,14 +382,17 @@ config X86_OOSTORE # P6_NOPs are a relatively minor optimization that require a family >= # 6 processor, except that it is broken on certain VIA chips. # Furthermore, AMD chips prefer a totally different sequence of NOPs -# (which work on all CPUs). As a result, disallow these if we're -# compiling X86_GENERIC but not X86_64 (these NOPs do work on all -# x86-64 capable chips); the list of processors in the right-hand clause -# are the cores that benefit from this optimization. +# (which work on all CPUs). In addition, it looks like Virtual PC +# does not understand them. +# +# As a result, disallow these if we're not compiling for X86_64 (these +# NOPs do work on all x86-64 capable chips); the list of processors in +# the right-hand clause are the cores that benefit from this optimization. # config X86_P6_NOP def_bool y - depends on (X86_64 || !X86_GENERIC) && (M686 || MPENTIUMII || MPENTIUMIII || MPENTIUMM || MCORE2 || MPENTIUM4 || MPSC) + depends on X86_64 + depends on (MCORE2 || MPENTIUM4 || MPSC) config X86_TSC def_bool y -- cgit v0.10.2 From d315492b1a6ba29da0fa2860759505ae1b2db857 Mon Sep 17 00:00:00 2001 From: Daniel Lezcano Date: Mon, 8 Sep 2008 13:17:27 -0700 Subject: netns : fix kernel panic in timewait socket destruction How to reproduce ? - create a network namespace - use tcp protocol and get timewait socket - exit the network namespace - after a moment (when the timewait socket is destroyed), the kernel panics. # BUG: unable to handle kernel NULL pointer dereference at 0000000000000007 IP: [] inet_twdr_do_twkill_work+0x6e/0xb8 PGD 119985067 PUD 11c5c0067 PMD 0 Oops: 0000 [1] SMP CPU 1 Modules linked in: ipv6 button battery ac loop dm_mod tg3 libphy ext3 jbd edd fan thermal processor thermal_sys sg sata_svw libata dock serverworks sd_mod scsi_mod ide_disk ide_core [last unloaded: freq_table] Pid: 0, comm: swapper Not tainted 2.6.27-rc2 #3 RIP: 0010:[] [] inet_twdr_do_twkill_work+0x6e/0xb8 RSP: 0018:ffff88011ff7fed0 EFLAGS: 00010246 RAX: ffffffffffffffff RBX: ffffffff82339420 RCX: ffff88011ff7ff30 RDX: 0000000000000001 RSI: ffff88011a4d03c0 RDI: ffff88011ac2fc00 RBP: ffffffff823392e0 R08: 0000000000000000 R09: ffff88002802a200 R10: ffff8800a5c4b000 R11: ffffffff823e4080 R12: ffff88011ac2fc00 R13: 0000000000000001 R14: 0000000000000001 R15: 0000000000000000 FS: 0000000041cbd940(0000) GS:ffff8800bff839c0(0000) knlGS:0000000000000000 CS: 0010 DS: 0018 ES: 0018 CR0: 000000008005003b CR2: 0000000000000007 CR3: 00000000bd87c000 CR4: 00000000000006e0 DR0: 0000000000000000 DR1: 0000000000000000 DR2: 0000000000000000 DR3: 0000000000000000 DR6: 00000000ffff0ff0 DR7: 0000000000000400 Process swapper (pid: 0, threadinfo ffff8800bff9e000, task ffff88011ff76690) Stack: ffffffff823392e0 0000000000000100 ffffffff821e3a3a 0000000000000008 0000000000000000 ffffffff821e3a61 ffff8800bff7c000 ffffffff8203c7e7 ffff88011ff7ff10 ffff88011ff7ff10 0000000000000021 ffffffff82351108 Call Trace: [] ? inet_twdr_hangman+0x0/0x9e [] ? inet_twdr_hangman+0x27/0x9e [] ? run_timer_softirq+0x12c/0x193 [] ? __do_softirq+0x5e/0xcd [] ? call_softirq+0x1c/0x28 [] ? do_softirq+0x2c/0x68 [] ? smp_apic_timer_interrupt+0x8e/0xa9 [] ? apic_timer_interrupt+0x66/0x70 [] ? default_idle+0x27/0x3b [] ? cpu_idle+0x5f/0x7d Code: e8 01 00 00 4c 89 e7 41 ff c5 e8 8d fd ff ff 49 8b 44 24 38 4c 89 e7 65 8b 14 25 24 00 00 00 89 d2 48 8b 80 e8 00 00 00 48 f7 d0 <48> 8b 04 d0 48 ff 40 58 e8 fc fc ff ff 48 89 df e8 c0 5f 04 00 RIP [] inet_twdr_do_twkill_work+0x6e/0xb8 RSP CR2: 0000000000000007 This patch provides a function to purge all timewait sockets related to a network namespace. The timewait sockets life cycle is not tied with the network namespace, that means the timewait sockets stay alive while the network namespace dies. The timewait sockets are for avoiding to receive a duplicate packet from the network, if the network namespace is freed, the network stack is removed, so no chance to receive any packets from the outside world. Furthermore, having a pending destruction timer on these sockets with a network namespace freed is not safe and will lead to an oops if the timer callback which try to access data belonging to the namespace like for example in: inet_twdr_do_twkill_work -> NET_INC_STATS_BH(twsk_net(tw), LINUX_MIB_TIMEWAITED); Purging the timewait sockets at the network namespace destruction will: 1) speed up memory freeing for the namespace 2) fix kernel panic on asynchronous timewait destruction Signed-off-by: Daniel Lezcano Acked-by: Denis V. Lunev Acked-by: Eric W. Biederman Signed-off-by: David S. Miller diff --git a/include/net/inet_timewait_sock.h b/include/net/inet_timewait_sock.h index 95c660c..9132490 100644 --- a/include/net/inet_timewait_sock.h +++ b/include/net/inet_timewait_sock.h @@ -208,6 +208,9 @@ extern void inet_twsk_schedule(struct inet_timewait_sock *tw, extern void inet_twsk_deschedule(struct inet_timewait_sock *tw, struct inet_timewait_death_row *twdr); +extern void inet_twsk_purge(struct net *net, struct inet_hashinfo *hashinfo, + struct inet_timewait_death_row *twdr, int family); + static inline struct net *twsk_net(const struct inet_timewait_sock *twsk) { diff --git a/net/ipv4/inet_timewait_sock.c b/net/ipv4/inet_timewait_sock.c index d985bd6..743f011 100644 --- a/net/ipv4/inet_timewait_sock.c +++ b/net/ipv4/inet_timewait_sock.c @@ -409,3 +409,38 @@ out: } EXPORT_SYMBOL_GPL(inet_twdr_twcal_tick); + +void inet_twsk_purge(struct net *net, struct inet_hashinfo *hashinfo, + struct inet_timewait_death_row *twdr, int family) +{ + struct inet_timewait_sock *tw; + struct sock *sk; + struct hlist_node *node; + int h; + + local_bh_disable(); + for (h = 0; h < (hashinfo->ehash_size); h++) { + struct inet_ehash_bucket *head = + inet_ehash_bucket(hashinfo, h); + rwlock_t *lock = inet_ehash_lockp(hashinfo, h); +restart: + write_lock(lock); + sk_for_each(sk, node, &head->twchain) { + + tw = inet_twsk(sk); + if (!net_eq(twsk_net(tw), net) || + tw->tw_family != family) + continue; + + atomic_inc(&tw->tw_refcnt); + write_unlock(lock); + inet_twsk_deschedule(tw, twdr); + inet_twsk_put(tw); + + goto restart; + } + write_unlock(lock); + } + local_bh_enable(); +} +EXPORT_SYMBOL_GPL(inet_twsk_purge); diff --git a/net/ipv4/tcp_ipv4.c b/net/ipv4/tcp_ipv4.c index 44c1e93..1b4fee2 100644 --- a/net/ipv4/tcp_ipv4.c +++ b/net/ipv4/tcp_ipv4.c @@ -2376,6 +2376,7 @@ static int __net_init tcp_sk_init(struct net *net) static void __net_exit tcp_sk_exit(struct net *net) { inet_ctl_sock_destroy(net->ipv4.tcp_sock); + inet_twsk_purge(net, &tcp_hashinfo, &tcp_death_row, AF_INET); } static struct pernet_operations __net_initdata tcp_sk_ops = { diff --git a/net/ipv6/tcp_ipv6.c b/net/ipv6/tcp_ipv6.c index 5b90b36..b585c85 100644 --- a/net/ipv6/tcp_ipv6.c +++ b/net/ipv6/tcp_ipv6.c @@ -2148,6 +2148,7 @@ static int tcpv6_net_init(struct net *net) static void tcpv6_net_exit(struct net *net) { inet_ctl_sock_destroy(net->ipv6.tcp_sk); + inet_twsk_purge(net, &tcp_hashinfo, &tcp_death_row, AF_INET6); } static struct pernet_operations tcpv6_net_ops = { -- cgit v0.10.2 From 8d4698f7a54a492a1b96c505b30fe750ae3e61d5 Mon Sep 17 00:00:00 2001 From: Stephen Hemminger Date: Mon, 8 Sep 2008 13:44:40 -0700 Subject: bridge: don't allow setting hello time to zero Dushan Tcholich reports that on his system ksoftirqd can consume between %6 to %10 of cpu time, and cause ~200 context switches per second. He then correlated this with a report by bdupree@techfinesse.com: http://marc.info/?l=linux-kernel&m=119613299024398&w=2 and the culprit cause seems to be starting the bridge interface. In particular, when starting the bridge interface, his scripts are specifying a hello timer interval of "0". The bridge hello time can't be safely set to values less than 1 second, otherwise it is possible to end up with a runaway timer. Signed-off-by: Stephen Hemminger Signed-off-by: David S. Miller diff --git a/net/bridge/br_ioctl.c b/net/bridge/br_ioctl.c index eeee218..5bbf073 100644 --- a/net/bridge/br_ioctl.c +++ b/net/bridge/br_ioctl.c @@ -188,15 +188,21 @@ static int old_dev_ioctl(struct net_device *dev, struct ifreq *rq, int cmd) return 0; case BRCTL_SET_BRIDGE_HELLO_TIME: + { + unsigned long t = clock_t_to_jiffies(args[1]); if (!capable(CAP_NET_ADMIN)) return -EPERM; + if (t < HZ) + return -EINVAL; + spin_lock_bh(&br->lock); - br->bridge_hello_time = clock_t_to_jiffies(args[1]); + br->bridge_hello_time = t; if (br_is_root_bridge(br)) br->hello_time = br->bridge_hello_time; spin_unlock_bh(&br->lock); return 0; + } case BRCTL_SET_BRIDGE_MAX_AGE: if (!capable(CAP_NET_ADMIN)) diff --git a/net/bridge/br_sysfs_br.c b/net/bridge/br_sysfs_br.c index 27d6a51..158dee8 100644 --- a/net/bridge/br_sysfs_br.c +++ b/net/bridge/br_sysfs_br.c @@ -29,11 +29,12 @@ */ static ssize_t store_bridge_parm(struct device *d, const char *buf, size_t len, - void (*set)(struct net_bridge *, unsigned long)) + int (*set)(struct net_bridge *, unsigned long)) { struct net_bridge *br = to_bridge(d); char *endp; unsigned long val; + int err; if (!capable(CAP_NET_ADMIN)) return -EPERM; @@ -43,9 +44,9 @@ static ssize_t store_bridge_parm(struct device *d, return -EINVAL; spin_lock_bh(&br->lock); - (*set)(br, val); + err = (*set)(br, val); spin_unlock_bh(&br->lock); - return len; + return err ? err : len; } @@ -56,12 +57,13 @@ static ssize_t show_forward_delay(struct device *d, return sprintf(buf, "%lu\n", jiffies_to_clock_t(br->forward_delay)); } -static void set_forward_delay(struct net_bridge *br, unsigned long val) +static int set_forward_delay(struct net_bridge *br, unsigned long val) { unsigned long delay = clock_t_to_jiffies(val); br->forward_delay = delay; if (br_is_root_bridge(br)) br->bridge_forward_delay = delay; + return 0; } static ssize_t store_forward_delay(struct device *d, @@ -80,12 +82,17 @@ static ssize_t show_hello_time(struct device *d, struct device_attribute *attr, jiffies_to_clock_t(to_bridge(d)->hello_time)); } -static void set_hello_time(struct net_bridge *br, unsigned long val) +static int set_hello_time(struct net_bridge *br, unsigned long val) { unsigned long t = clock_t_to_jiffies(val); + + if (t < HZ) + return -EINVAL; + br->hello_time = t; if (br_is_root_bridge(br)) br->bridge_hello_time = t; + return 0; } static ssize_t store_hello_time(struct device *d, @@ -104,12 +111,13 @@ static ssize_t show_max_age(struct device *d, struct device_attribute *attr, jiffies_to_clock_t(to_bridge(d)->max_age)); } -static void set_max_age(struct net_bridge *br, unsigned long val) +static int set_max_age(struct net_bridge *br, unsigned long val) { unsigned long t = clock_t_to_jiffies(val); br->max_age = t; if (br_is_root_bridge(br)) br->bridge_max_age = t; + return 0; } static ssize_t store_max_age(struct device *d, struct device_attribute *attr, @@ -126,9 +134,10 @@ static ssize_t show_ageing_time(struct device *d, return sprintf(buf, "%lu\n", jiffies_to_clock_t(br->ageing_time)); } -static void set_ageing_time(struct net_bridge *br, unsigned long val) +static int set_ageing_time(struct net_bridge *br, unsigned long val) { br->ageing_time = clock_t_to_jiffies(val); + return 0; } static ssize_t store_ageing_time(struct device *d, @@ -180,9 +189,10 @@ static ssize_t show_priority(struct device *d, struct device_attribute *attr, (br->bridge_id.prio[0] << 8) | br->bridge_id.prio[1]); } -static void set_priority(struct net_bridge *br, unsigned long val) +static int set_priority(struct net_bridge *br, unsigned long val) { br_stp_set_bridge_priority(br, (u16) val); + return 0; } static ssize_t store_priority(struct device *d, struct device_attribute *attr, -- cgit v0.10.2 From af904deaf6da3f3285eb0a06a3dc6a1af0251030 Mon Sep 17 00:00:00 2001 From: Chuck Lever Date: Mon, 8 Sep 2008 11:58:13 -0400 Subject: NFS: Restore missing hunk in NFS mount option parser Automounter maps can contain mount options valid for other NFS implementations but not for Linux. The Linux automounter uses the mount command's "-s" command line option ("s" for "sloppy") so that mount requests containing such options are not rejected. Commit f45663ce5fb30f76a3414ab3ac69f4dd320e760a attempted to address a known regression with text-based NFS mount option parsing. Unrecognized mount options would cause mount requests to fail, even if the "-s" option was used on the mount command line. Unfortunately, this commit was not complete as submitted. It adds a new mount option, "sloppy". But it is missing a hunk, so it now allows NFS mounts with unrecognized mount options, even if the "sloppy" option is not present. This could be a problem if a required critical mount option such as "sync" is misspelled, for example, and is considered a regression from 2.6.26. This patch restores the missing hunk. Now, the default behavior of text-based NFS mount options is as before: any unrecognized mount option will cause the mount to fail. Please include this in 2.6.27-rc. Thanks to Neil Brown for reporting this. Signed-off-by: Chuck Lever Acked-by: J. Bruce Fields Signed-off-by: Linus Torvalds diff --git a/fs/nfs/super.c b/fs/nfs/super.c index 9abcd2b..e9b2017 100644 --- a/fs/nfs/super.c +++ b/fs/nfs/super.c @@ -1279,6 +1279,12 @@ static int nfs_parse_mount_options(char *raw, } } + if (errors > 0) { + dfprintk(MOUNT, "NFS: parsing encountered %d error%s\n", + errors, (errors == 1 ? "" : "s")); + if (!sloppy) + return 0; + } return 1; out_nomem: -- cgit v0.10.2 From 06dd881f59b3c07a430cdcbef2197f9b6dc79ae8 Mon Sep 17 00:00:00 2001 From: Jason Wessel Date: Mon, 8 Sep 2008 14:53:37 +0100 Subject: usb: fix null deferences in low level usb serial The hw interface drivers for the usb serial devices deference the tty structure to set up the parameters for the initial console. The tty structure should be passed as a parameter to the set_termios() call. Signed-off-by: Jason Wessel Signed-off-by: Alan Cox Signed-off-by: Linus Torvalds diff --git a/drivers/usb/serial/console.c b/drivers/usb/serial/console.c index 7b74238..e980766 100644 --- a/drivers/usb/serial/console.c +++ b/drivers/usb/serial/console.c @@ -161,7 +161,7 @@ static int usb_console_setup(struct console *co, char *options) if (serial->type->set_termios) { termios->c_cflag = cflag; tty_termios_encode_baud_rate(termios, baud, baud); - serial->type->set_termios(NULL, port, &dummy); + serial->type->set_termios(tty, port, &dummy); port->port.tty = NULL; kfree(termios); -- cgit v0.10.2 From a46add72f79bb8196f07a860adddd312ca398eec Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Uwe=20Kleine-K=C3=B6nig?= Date: Tue, 9 Sep 2008 00:11:39 +0200 Subject: Fix format of MAINTAINERS MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit ... one entry lacked a colon which broke one of my scripts. Signed-off-by: Uwe Kleine-König Signed-off-by: Linus Torvalds diff --git a/MAINTAINERS b/MAINTAINERS index af27945..b3e92fb 100644 --- a/MAINTAINERS +++ b/MAINTAINERS @@ -1593,7 +1593,7 @@ S: Supported EMBEDDED LINUX P: Paul Gortmaker M: paul.gortmaker@windriver.com -P David Woodhouse +P: David Woodhouse M: dwmw2@infradead.org L: linux-embedded@vger.kernel.org S: Maintained -- cgit v0.10.2 From 2eb2f77900d62796934bcd43c4089e444cf1179e Mon Sep 17 00:00:00 2001 From: "David S. Miller" Date: Mon, 8 Sep 2008 17:21:07 -0700 Subject: sparc64: Disable timer interrupts in fixup_irqs(). When a CPU is offlined, we leave the timer interrupts disabled because fixup_irqs() does not explicitly take care of that case. Fix this by invoking tick_ops->disable_irq(). Based upon analysis done by Paul E. McKenney. Signed-off-by: David S. Miller diff --git a/arch/sparc64/kernel/irq.c b/arch/sparc64/kernel/irq.c index 9b6689d..2396388 100644 --- a/arch/sparc64/kernel/irq.c +++ b/arch/sparc64/kernel/irq.c @@ -792,6 +792,8 @@ void fixup_irqs(void) } spin_unlock_irqrestore(&irq_desc[irq].lock, flags); } + + tick_ops->disable_irq(); } #endif -- cgit v0.10.2 From f1c08ca559387ab30992055596d54061dfa022b1 Mon Sep 17 00:00:00 2001 From: Marcel Holtmann Date: Tue, 9 Sep 2008 07:19:19 +0200 Subject: [Bluetooth] Fix reference counting during ACL config stage The ACL config stage keeps holding a reference count on incoming connections when requesting the extended features. This results in keeping an ACL link up without any users. The problem here is that the Bluetooth specification doesn't define an ownership of the ACL link and thus it can happen that the implementation on the initiator side doesn't care about disconnecting unused links. In this case the acceptor needs to take care of this. Signed-off-by: Marcel Holtmann diff --git a/net/bluetooth/hci_event.c b/net/bluetooth/hci_event.c index 0e3db28..ad7a553 100644 --- a/net/bluetooth/hci_event.c +++ b/net/bluetooth/hci_event.c @@ -1605,14 +1605,11 @@ static inline void hci_remote_ext_features_evt(struct hci_dev *hdev, struct sk_b if (conn->state == BT_CONFIG) { if (!ev->status && hdev->ssp_mode > 0 && - conn->ssp_mode > 0) { - if (conn->out) { - struct hci_cp_auth_requested cp; - cp.handle = ev->handle; - hci_send_cmd(hdev, - HCI_OP_AUTH_REQUESTED, + conn->ssp_mode > 0 && conn->out) { + struct hci_cp_auth_requested cp; + cp.handle = ev->handle; + hci_send_cmd(hdev, HCI_OP_AUTH_REQUESTED, sizeof(cp), &cp); - } } else { conn->state = BT_CONNECTED; hci_proto_connect_cfm(conn, ev->status); -- cgit v0.10.2 From 09ab6f4c2376a0fc31abde1e2991513f900ea825 Mon Sep 17 00:00:00 2001 From: Marcel Holtmann Date: Tue, 9 Sep 2008 07:19:20 +0200 Subject: [Bluetooth] Enforce correct authentication requirements With the introduction of Security Mode 4 and Simple Pairing from the Bluetooth 2.1 specification it became mandatory that the initiator requires authentication and encryption before any L2CAP channel can be established. The only exception here is PSM 1 for the service discovery protocol (SDP). It is meant to be used without any encryption since it contains only public information. This is how Bluetooth 2.0 and before handle connections on PSM 1. For Bluetooth 2.1 devices the pairing procedure differentiates between no bonding, general bonding and dedicated bonding. The L2CAP layer wrongly uses always general bonding when creating new connections, but it should not do this for SDP connections. In this case the authentication requirement should be no bonding and the just-works model should be used, but in case of non-SDP connection it is required to use general bonding. If the new connection requires man-in-the-middle (MITM) protection, it also first wrongly creates an unauthenticated link key and then later on requests an upgrade to an authenticated link key to provide full MITM protection. With Simple Pairing the link key generation is an expensive operation (compared to Bluetooth 2.0 and before) and doing this twice during a connection setup causes a noticeable delay when establishing a new connection. This should be avoided to not regress from the expected Bluetooth 2.0 connection times. The authentication requirements are known up-front and so enforce them. To fulfill these requirements the hci_connect() function has been extended with an authentication requirement parameter that will be stored inside the connection information and can be retrieved by userspace at any time. This allows the correct IO capabilities exchange and results in the expected behavior. Signed-off-by: Marcel Holtmann diff --git a/include/net/bluetooth/hci_core.h b/include/net/bluetooth/hci_core.h index cbf7510..5e785b9 100644 --- a/include/net/bluetooth/hci_core.h +++ b/include/net/bluetooth/hci_core.h @@ -325,7 +325,7 @@ int hci_conn_del(struct hci_conn *conn); void hci_conn_hash_flush(struct hci_dev *hdev); void hci_conn_check_pending(struct hci_dev *hdev); -struct hci_conn *hci_connect(struct hci_dev *hdev, int type, bdaddr_t *src); +struct hci_conn *hci_connect(struct hci_dev *hdev, int type, bdaddr_t *dst, __u8 auth_type); int hci_conn_auth(struct hci_conn *conn); int hci_conn_encrypt(struct hci_conn *conn); int hci_conn_change_link_key(struct hci_conn *conn); diff --git a/net/bluetooth/hci_conn.c b/net/bluetooth/hci_conn.c index ca8d052..a2f9efa 100644 --- a/net/bluetooth/hci_conn.c +++ b/net/bluetooth/hci_conn.c @@ -330,7 +330,7 @@ EXPORT_SYMBOL(hci_get_route); /* Create SCO or ACL connection. * Device _must_ be locked */ -struct hci_conn *hci_connect(struct hci_dev *hdev, int type, bdaddr_t *dst) +struct hci_conn *hci_connect(struct hci_dev *hdev, int type, bdaddr_t *dst, __u8 auth_type) { struct hci_conn *acl; struct hci_conn *sco; @@ -344,8 +344,10 @@ struct hci_conn *hci_connect(struct hci_dev *hdev, int type, bdaddr_t *dst) hci_conn_hold(acl); - if (acl->state == BT_OPEN || acl->state == BT_CLOSED) + if (acl->state == BT_OPEN || acl->state == BT_CLOSED) { + acl->auth_type = auth_type; hci_acl_connect(acl); + } if (type == ACL_LINK) return acl; @@ -381,7 +383,7 @@ int hci_conn_auth(struct hci_conn *conn) if (conn->ssp_mode > 0 && conn->hdev->ssp_mode > 0) { if (!(conn->auth_type & 0x01)) { - conn->auth_type = HCI_AT_GENERAL_BONDING_MITM; + conn->auth_type |= 0x01; conn->link_mode &= ~HCI_LM_AUTH; } } diff --git a/net/bluetooth/l2cap.c b/net/bluetooth/l2cap.c index 3396d5b..a96d6de 100644 --- a/net/bluetooth/l2cap.c +++ b/net/bluetooth/l2cap.c @@ -55,7 +55,7 @@ #define BT_DBG(D...) #endif -#define VERSION "2.10" +#define VERSION "2.11" static u32 l2cap_feat_mask = 0x0000; @@ -778,6 +778,7 @@ static int l2cap_do_connect(struct sock *sk) struct l2cap_conn *conn; struct hci_conn *hcon; struct hci_dev *hdev; + __u8 auth_type; int err = 0; BT_DBG("%s -> %s psm 0x%2.2x", batostr(src), batostr(dst), l2cap_pi(sk)->psm); @@ -789,7 +790,21 @@ static int l2cap_do_connect(struct sock *sk) err = -ENOMEM; - hcon = hci_connect(hdev, ACL_LINK, dst); + if (l2cap_pi(sk)->link_mode & L2CAP_LM_AUTH || + l2cap_pi(sk)->link_mode & L2CAP_LM_ENCRYPT || + l2cap_pi(sk)->link_mode & L2CAP_LM_SECURE) { + if (l2cap_pi(sk)->psm == cpu_to_le16(0x0001)) + auth_type = HCI_AT_NO_BONDING_MITM; + else + auth_type = HCI_AT_GENERAL_BONDING_MITM; + } else { + if (l2cap_pi(sk)->psm == cpu_to_le16(0x0001)) + auth_type = HCI_AT_NO_BONDING; + else + auth_type = HCI_AT_GENERAL_BONDING; + } + + hcon = hci_connect(hdev, ACL_LINK, dst, auth_type); if (!hcon) goto done; diff --git a/net/bluetooth/sco.c b/net/bluetooth/sco.c index a16011f..0cc91e6 100644 --- a/net/bluetooth/sco.c +++ b/net/bluetooth/sco.c @@ -200,7 +200,7 @@ static int sco_connect(struct sock *sk) else type = SCO_LINK; - hcon = hci_connect(hdev, type, dst); + hcon = hci_connect(hdev, type, dst, HCI_AT_NO_BONDING); if (!hcon) goto done; -- cgit v0.10.2 From e7c29cb16c833441fd2160642bb13025f4e7ac70 Mon Sep 17 00:00:00 2001 From: Marcel Holtmann Date: Tue, 9 Sep 2008 07:19:20 +0200 Subject: [Bluetooth] Reject L2CAP connections on an insecure ACL link The Security Mode 4 of the Bluetooth 2.1 specification has strict authentication and encryption requirements. It is the initiators job to create a secure ACL link. However in case of malicious devices, the acceptor has to make sure that the ACL is encrypted before allowing any kind of L2CAP connection. The only exception here is the PSM 1 for the service discovery protocol, because that is allowed to run on an insecure ACL link. Previously it was enough to reject a L2CAP connection during the connection setup phase, but with Bluetooth 2.1 it is forbidden to do any L2CAP protocol exchange on an insecure link (except SDP). The new hci_conn_check_link_mode() function can be used to check the integrity of an ACL link. This functions also takes care of the cases where Security Mode 4 is disabled or one of the devices is based on an older specification. Signed-off-by: Marcel Holtmann diff --git a/include/net/bluetooth/hci_core.h b/include/net/bluetooth/hci_core.h index 5e785b9..46a43b7 100644 --- a/include/net/bluetooth/hci_core.h +++ b/include/net/bluetooth/hci_core.h @@ -326,6 +326,7 @@ void hci_conn_hash_flush(struct hci_dev *hdev); void hci_conn_check_pending(struct hci_dev *hdev); struct hci_conn *hci_connect(struct hci_dev *hdev, int type, bdaddr_t *dst, __u8 auth_type); +int hci_conn_check_link_mode(struct hci_conn *conn); int hci_conn_auth(struct hci_conn *conn); int hci_conn_encrypt(struct hci_conn *conn); int hci_conn_change_link_key(struct hci_conn *conn); diff --git a/net/bluetooth/af_bluetooth.c b/net/bluetooth/af_bluetooth.c index 1edfdf4..f6348e0 100644 --- a/net/bluetooth/af_bluetooth.c +++ b/net/bluetooth/af_bluetooth.c @@ -49,7 +49,7 @@ #define BT_DBG(D...) #endif -#define VERSION "2.12" +#define VERSION "2.13" /* Bluetooth sockets */ #define BT_MAX_PROTO 8 diff --git a/net/bluetooth/hci_conn.c b/net/bluetooth/hci_conn.c index a2f9efa..b700242 100644 --- a/net/bluetooth/hci_conn.c +++ b/net/bluetooth/hci_conn.c @@ -376,6 +376,19 @@ struct hci_conn *hci_connect(struct hci_dev *hdev, int type, bdaddr_t *dst, __u8 } EXPORT_SYMBOL(hci_connect); +/* Check link security requirement */ +int hci_conn_check_link_mode(struct hci_conn *conn) +{ + BT_DBG("conn %p", conn); + + if (conn->ssp_mode > 0 && conn->hdev->ssp_mode > 0 && + !(conn->link_mode & HCI_LM_ENCRYPT)) + return 0; + + return 1; +} +EXPORT_SYMBOL(hci_conn_check_link_mode); + /* Authenticate remote device */ int hci_conn_auth(struct hci_conn *conn) { diff --git a/net/bluetooth/l2cap.c b/net/bluetooth/l2cap.c index a96d6de..9610a9c 100644 --- a/net/bluetooth/l2cap.c +++ b/net/bluetooth/l2cap.c @@ -1568,10 +1568,10 @@ static inline int l2cap_connect_req(struct l2cap_conn *conn, struct l2cap_cmd_hd struct l2cap_conn_req *req = (struct l2cap_conn_req *) data; struct l2cap_conn_rsp rsp; struct sock *sk, *parent; - int result, status = 0; + int result, status = L2CAP_CS_NO_INFO; u16 dcid = 0, scid = __le16_to_cpu(req->scid); - __le16 psm = req->psm; + __le16 psm = req->psm; BT_DBG("psm 0x%2.2x scid 0x%4.4x", psm, scid); @@ -1582,6 +1582,13 @@ static inline int l2cap_connect_req(struct l2cap_conn *conn, struct l2cap_cmd_hd goto sendresp; } + /* Check if the ACL is secure enough (if not SDP) */ + if (psm != cpu_to_le16(0x0001) && + !hci_conn_check_link_mode(conn->hcon)) { + result = L2CAP_CR_SEC_BLOCK; + goto response; + } + result = L2CAP_CR_NO_MEM; /* Check for backlog size */ @@ -2239,7 +2246,7 @@ static int l2cap_auth_cfm(struct hci_conn *hcon, u8 status) rsp.scid = cpu_to_le16(l2cap_pi(sk)->dcid); rsp.dcid = cpu_to_le16(l2cap_pi(sk)->scid); rsp.result = cpu_to_le16(result); - rsp.status = cpu_to_le16(0); + rsp.status = cpu_to_le16(L2CAP_CS_NO_INFO); l2cap_send_cmd(conn, l2cap_pi(sk)->ident, L2CAP_CONN_RSP, sizeof(rsp), &rsp); } @@ -2311,7 +2318,7 @@ static int l2cap_encrypt_cfm(struct hci_conn *hcon, u8 status, u8 encrypt) rsp.scid = cpu_to_le16(l2cap_pi(sk)->dcid); rsp.dcid = cpu_to_le16(l2cap_pi(sk)->scid); rsp.result = cpu_to_le16(result); - rsp.status = cpu_to_le16(0); + rsp.status = cpu_to_le16(L2CAP_CS_NO_INFO); l2cap_send_cmd(conn, l2cap_pi(sk)->ident, L2CAP_CONN_RSP, sizeof(rsp), &rsp); } -- cgit v0.10.2 From 3d6e48f43340343d97839eadb1ab7b6a3ea98797 Mon Sep 17 00:00:00 2001 From: Jarod Wilson Date: Tue, 9 Sep 2008 12:38:56 +0200 Subject: [S390] CVE-2008-1514: prevent ptrace padding area read/write in 31-bit mode When running a 31-bit ptrace, on either an s390 or s390x kernel, reads and writes into a padding area in struct user_regs_struct32 will result in a kernel panic. This is also known as CVE-2008-1514. Test case available here: http://sources.redhat.com/cgi-bin/cvsweb.cgi/~checkout~/tests/ptrace-tests/tests/user-area-padding.c?cvsroot=systemtap Steps to reproduce: 1) wget the above 2) gcc -o user-area-padding-31bit user-area-padding.c -Wall -ggdb2 -D_GNU_SOURCE -m31 3) ./user-area-padding-31bit Test status ----------- Without patch, both s390 and s390x kernels panic. With patch, the test case, as well as the gdb testsuite, pass without incident, padding area reads returning zero, writes ignored. Nb: original version returned -EINVAL on write attempts, which broke the gdb test and made the test case slightly unhappy, Jan Kratochvil suggested the change to return 0 on write attempts. Signed-off-by: Jarod Wilson Tested-by: Jan Kratochvil Signed-off-by: Martin Schwidefsky diff --git a/arch/s390/kernel/compat_ptrace.h b/arch/s390/kernel/compat_ptrace.h index cde81fa..a2be3a9 100644 --- a/arch/s390/kernel/compat_ptrace.h +++ b/arch/s390/kernel/compat_ptrace.h @@ -42,6 +42,7 @@ struct user_regs_struct32 u32 gprs[NUM_GPRS]; u32 acrs[NUM_ACRS]; u32 orig_gpr2; + /* nb: there's a 4-byte hole here */ s390_fp_regs fp_regs; /* * These per registers are in here so that gdb can modify them diff --git a/arch/s390/kernel/ptrace.c b/arch/s390/kernel/ptrace.c index 2815bfe..c8b0828 100644 --- a/arch/s390/kernel/ptrace.c +++ b/arch/s390/kernel/ptrace.c @@ -170,6 +170,13 @@ static unsigned long __peek_user(struct task_struct *child, addr_t addr) */ tmp = (addr_t) task_pt_regs(child)->orig_gpr2; + } else if (addr < (addr_t) &dummy->regs.fp_regs) { + /* + * prevent reads of padding hole between + * orig_gpr2 and fp_regs on s390. + */ + tmp = 0; + } else if (addr < (addr_t) (&dummy->regs.fp_regs + 1)) { /* * floating point regs. are stored in the thread structure @@ -270,6 +277,13 @@ static int __poke_user(struct task_struct *child, addr_t addr, addr_t data) */ task_pt_regs(child)->orig_gpr2 = data; + } else if (addr < (addr_t) &dummy->regs.fp_regs) { + /* + * prevent writes of padding hole between + * orig_gpr2 and fp_regs on s390. + */ + return 0; + } else if (addr < (addr_t) (&dummy->regs.fp_regs + 1)) { /* * floating point regs. are stored in the thread structure @@ -428,6 +442,13 @@ static u32 __peek_user_compat(struct task_struct *child, addr_t addr) */ tmp = *(__u32*)((addr_t) &task_pt_regs(child)->orig_gpr2 + 4); + } else if (addr < (addr_t) &dummy32->regs.fp_regs) { + /* + * prevent reads of padding hole between + * orig_gpr2 and fp_regs on s390. + */ + tmp = 0; + } else if (addr < (addr_t) (&dummy32->regs.fp_regs + 1)) { /* * floating point regs. are stored in the thread structure @@ -514,6 +535,13 @@ static int __poke_user_compat(struct task_struct *child, */ *(__u32*)((addr_t) &task_pt_regs(child)->orig_gpr2 + 4) = tmp; + } else if (addr < (addr_t) &dummy32->regs.fp_regs) { + /* + * prevent writess of padding hole between + * orig_gpr2 and fp_regs on s390. + */ + return 0; + } else if (addr < (addr_t) (&dummy32->regs.fp_regs + 1)) { /* * floating point regs. are stored in the thread structure -- cgit v0.10.2 From a2164b8174f13b7315c3f45c0b48dec619285096 Mon Sep 17 00:00:00 2001 From: Cornelia Huck Date: Tue, 9 Sep 2008 12:38:57 +0200 Subject: [S390] cio: Correct cleanup on error. Fix cleanup on error in chp_new() and init_channel_subsystem() (must not call kfree() on structures that had been registered). Signed-off-by: Cornelia Huck Signed-off-by: Martin Schwidefsky diff --git a/drivers/s390/cio/chp.c b/drivers/s390/cio/chp.c index db00b05..f1216cf 100644 --- a/drivers/s390/cio/chp.c +++ b/drivers/s390/cio/chp.c @@ -423,7 +423,7 @@ int chp_new(struct chp_id chpid) ret = sysfs_create_group(&chp->dev.kobj, &chp_attr_group); if (ret) { device_unregister(&chp->dev); - goto out_free; + goto out; } mutex_lock(&channel_subsystems[chpid.cssid]->mutex); if (channel_subsystems[chpid.cssid]->cm_enabled) { @@ -432,14 +432,15 @@ int chp_new(struct chp_id chpid) sysfs_remove_group(&chp->dev.kobj, &chp_attr_group); device_unregister(&chp->dev); mutex_unlock(&channel_subsystems[chpid.cssid]->mutex); - goto out_free; + goto out; } } channel_subsystems[chpid.cssid]->chps[chpid.id] = chp; mutex_unlock(&channel_subsystems[chpid.cssid]->mutex); - return ret; + goto out; out_free: kfree(chp); +out: return ret; } diff --git a/drivers/s390/cio/css.c b/drivers/s390/cio/css.c index 51489ef..1261e1a 100644 --- a/drivers/s390/cio/css.c +++ b/drivers/s390/cio/css.c @@ -633,6 +633,11 @@ channel_subsystem_release(struct device *dev) css = to_css(dev); mutex_destroy(&css->mutex); + if (css->pseudo_subchannel) { + /* Implies that it has been generated but never registered. */ + css_subchannel_release(&css->pseudo_subchannel->dev); + css->pseudo_subchannel = NULL; + } kfree(css); } @@ -785,11 +790,15 @@ init_channel_subsystem (void) } channel_subsystems[i] = css; ret = setup_css(i); - if (ret) - goto out_free; + if (ret) { + kfree(channel_subsystems[i]); + goto out_unregister; + } ret = device_register(&css->device); - if (ret) - goto out_free_all; + if (ret) { + put_device(&css->device); + goto out_unregister; + } if (css_chsc_characteristics.secm) { ret = device_create_file(&css->device, &dev_attr_cm_enable); @@ -802,7 +811,7 @@ init_channel_subsystem (void) } ret = register_reboot_notifier(&css_reboot_notifier); if (ret) - goto out_pseudo; + goto out_unregister; css_init_done = 1; /* Enable default isc for I/O subchannels. */ @@ -810,18 +819,12 @@ init_channel_subsystem (void) for_each_subchannel(__init_channel_subsystem, NULL); return 0; -out_pseudo: - device_unregister(&channel_subsystems[i]->pseudo_subchannel->dev); out_file: - device_remove_file(&channel_subsystems[i]->device, - &dev_attr_cm_enable); + if (css_chsc_characteristics.secm) + device_remove_file(&channel_subsystems[i]->device, + &dev_attr_cm_enable); out_device: device_unregister(&channel_subsystems[i]->device); -out_free_all: - kfree(channel_subsystems[i]->pseudo_subchannel->lock); - kfree(channel_subsystems[i]->pseudo_subchannel); -out_free: - kfree(channel_subsystems[i]); out_unregister: while (i > 0) { struct channel_subsystem *css; @@ -829,6 +832,7 @@ out_unregister: i--; css = channel_subsystems[i]; device_unregister(&css->pseudo_subchannel->dev); + css->pseudo_subchannel = NULL; if (css_chsc_characteristics.secm) device_remove_file(&css->device, &dev_attr_cm_enable); -- cgit v0.10.2 From c91ebe496120e05301465fff31094bfecf798e9f Mon Sep 17 00:00:00 2001 From: Cornelia Huck Date: Tue, 9 Sep 2008 12:38:58 +0200 Subject: [S390] cio: handle ssch() return codes correctly. ssch() has two classes of return codes: - condition codes (0-3) which need to be translated to Linux error codes - Linux error codes (-EIO on exceptions) which should be passed to the caller (instead of erronously being handled like condition code 3) Signed-off-by: Cornelia Huck Signed-off-by: Martin Schwidefsky diff --git a/drivers/s390/cio/cio.c b/drivers/s390/cio/cio.c index 33bff8f..5954b90 100644 --- a/drivers/s390/cio/cio.c +++ b/drivers/s390/cio/cio.c @@ -208,8 +208,10 @@ cio_start_key (struct subchannel *sch, /* subchannel structure */ case 1: /* status pending */ case 2: /* busy */ return -EBUSY; - default: /* device/path not operational */ + case 3: /* device/path not operational */ return cio_start_handle_notoper(sch, lpm); + default: + return ccode; } } -- cgit v0.10.2 From b301ea8c81b13123761772f344faf606c76ba174 Mon Sep 17 00:00:00 2001 From: Peter Oberparleiter Date: Tue, 9 Sep 2008 12:38:59 +0200 Subject: [S390] cio: allow offline processing for disconnected devices When disconnected ccw devices are removed, the device has to be set offline, otherwise there will be side effects including a reference count imbalance. This patch modifies ccw_device_offline to work for devices in disconnecte/not operational state. ccw_device_offline is called by cio for devices which are online during device removal. Signed-off-by: Peter Oberparleiter Signed-off-by: Martin Schwidefsky diff --git a/drivers/s390/cio/device_fsm.c b/drivers/s390/cio/device_fsm.c index 550508d..84cc9ea 100644 --- a/drivers/s390/cio/device_fsm.c +++ b/drivers/s390/cio/device_fsm.c @@ -658,6 +658,13 @@ ccw_device_offline(struct ccw_device *cdev) { struct subchannel *sch; + /* Allow ccw_device_offline while disconnected. */ + if (cdev->private->state == DEV_STATE_DISCONNECTED || + cdev->private->state == DEV_STATE_NOT_OPER) { + cdev->private->flags.donotify = 0; + ccw_device_done(cdev, DEV_STATE_NOT_OPER); + return 0; + } if (ccw_device_is_orphan(cdev)) { ccw_device_done(cdev, DEV_STATE_OFFLINE); return 0; -- cgit v0.10.2 From 225f40055f779032974a9fce7b2f9c9eda04ff58 Mon Sep 17 00:00:00 2001 From: Herbert Xu Date: Tue, 9 Sep 2008 05:23:37 -0700 Subject: ipsec: Restore larval states and socket policies in dump The commit commit 4c563f7669c10a12354b72b518c2287ffc6ebfb3 ("[XFRM]: Speed up xfrm_policy and xfrm_state walking") inadvertently removed larval states and socket policies from netlink dumps. This patch restores them. Signed-off-by: Herbert Xu Signed-off-by: David S. Miller diff --git a/net/xfrm/xfrm_policy.c b/net/xfrm/xfrm_policy.c index 46914b7..b7754b1 100644 --- a/net/xfrm/xfrm_policy.c +++ b/net/xfrm/xfrm_policy.c @@ -1077,6 +1077,7 @@ static void __xfrm_policy_link(struct xfrm_policy *pol, int dir) struct hlist_head *chain = policy_hash_bysel(&pol->selector, pol->family, dir); + list_add_tail(&pol->bytype, &xfrm_policy_bytype[pol->type]); hlist_add_head(&pol->bydst, chain); hlist_add_head(&pol->byidx, xfrm_policy_byidx+idx_hash(pol->index)); xfrm_policy_count[dir]++; diff --git a/net/xfrm/xfrm_state.c b/net/xfrm/xfrm_state.c index 7bd62f6..0a8f09c 100644 --- a/net/xfrm/xfrm_state.c +++ b/net/xfrm/xfrm_state.c @@ -858,6 +858,7 @@ xfrm_state_find(xfrm_address_t *daddr, xfrm_address_t *saddr, if (km_query(x, tmpl, pol) == 0) { x->km.state = XFRM_STATE_ACQ; + list_add_tail(&x->all, &xfrm_state_all); hlist_add_head(&x->bydst, xfrm_state_bydst+h); h = xfrm_src_hash(daddr, saddr, family); hlist_add_head(&x->bysrc, xfrm_state_bysrc+h); @@ -1055,6 +1056,7 @@ static struct xfrm_state *__find_acq_core(unsigned short family, u8 mode, u32 re xfrm_state_hold(x); x->timer.expires = jiffies + sysctl_xfrm_acq_expires*HZ; add_timer(&x->timer); + list_add_tail(&x->all, &xfrm_state_all); hlist_add_head(&x->bydst, xfrm_state_bydst+h); h = xfrm_src_hash(daddr, saddr, family); hlist_add_head(&x->bysrc, xfrm_state_bysrc+h); -- cgit v0.10.2 From adaae7215e5130e5ce1ac3ee390e5a23101b09b2 Mon Sep 17 00:00:00 2001 From: Christoph Hellwig Date: Tue, 9 Sep 2008 20:02:01 +0200 Subject: update Documentation/filesystems/Locking for 2.6.27 changes In the 2.6.27 circle ->fasync lost the BKL, and the last remaining ->open variant that takes the BKL is also gone. ->get_sb and ->kill_sb didn't have BKL forever, so updated the entries while we're at that. Signed-off-by: Christoph Hellwig Signed-off-by: Linus Torvalds diff --git a/Documentation/filesystems/Locking b/Documentation/filesystems/Locking index 680fb56..8362860 100644 --- a/Documentation/filesystems/Locking +++ b/Documentation/filesystems/Locking @@ -144,8 +144,8 @@ prototypes: void (*kill_sb) (struct super_block *); locking rules: may block BKL -get_sb yes yes -kill_sb yes yes +get_sb yes no +kill_sb yes no ->get_sb() returns error or 0 with locked superblock attached to the vfsmount (exclusive on ->s_umount). @@ -409,12 +409,12 @@ ioctl: yes (see below) unlocked_ioctl: no (see below) compat_ioctl: no mmap: no -open: maybe (see below) +open: no flush: no release: no fsync: no (see below) aio_fsync: no -fasync: yes (see below) +fasync: no lock: yes readv: no writev: no @@ -431,13 +431,6 @@ For many filesystems, it is probably safe to acquire the inode semaphore. Note some filesystems (i.e. remote ones) provide no protection for i_size so you will need to use the BKL. -->open() locking is in-transit: big lock partially moved into the methods. -The only exception is ->open() in the instances of file_operations that never -end up in ->i_fop/->proc_fops, i.e. ones that belong to character devices -(chrdev_open() takes lock before replacing ->f_op and calling the secondary -method. As soon as we fix the handling of module reference counters all -instances of ->open() will be called without the BKL. - Note: ext2_release() was *the* source of contention on fs-intensive loads and dropping BKL on ->release() helps to get rid of that (we still grab BKL for cases when we close a file that had been opened r/w, but that -- cgit v0.10.2 From 7ae115b4f50d3c5824f1a15e572b5de9d1b06d35 Mon Sep 17 00:00:00 2001 From: Chris Snook Date: Tue, 9 Sep 2008 03:26:57 -0400 Subject: MAINTAINERS: add Atheros maintainer for atlx Jie Yang at Atheros is getting more directly involved with upstream work on the atl* drivers. This patch changes the ATL1 entry to ATLX (atl2 support posted to netdev today) and adds him as a maintainer. Signed-off-by: Linus Torvalds diff --git a/MAINTAINERS b/MAINTAINERS index b3e92fb..186be3b 100644 --- a/MAINTAINERS +++ b/MAINTAINERS @@ -750,11 +750,13 @@ P: Ville Syrjala M: syrjala@sci.fi S: Maintained -ATL1 ETHERNET DRIVER +ATLX ETHERNET DRIVERS P: Jay Cliburn M: jcliburn@gmail.com P: Chris Snook M: csnook@redhat.com +P: Jie Yang +M: jie.yang@atheros.com L: atl1-devel@lists.sourceforge.net W: http://sourceforge.net/projects/atl1 W: http://atl1.sourceforge.net -- cgit v0.10.2 From deac93df26b20cf8438339b5935b5f5643bc30c9 Mon Sep 17 00:00:00 2001 From: James Bottomley Date: Wed, 3 Sep 2008 20:43:36 -0500 Subject: lib: Correct printk %pF to work on all architectures It was introduced by "vsprintf: add support for '%pS' and '%pF' pointer formats" in commit 0fe1ef24f7bd0020f29ffe287dfdb9ead33ca0b2. However, the current way its coded doesn't work on parisc64. For two reasons: 1) parisc isn't in the #ifdef and 2) parisc has a different format for function descriptors Make dereference_function_descriptor() more accommodating by allowing architecture overrides. I put the three overrides (for parisc64, ppc64 and ia64) in arch/kernel/module.c because that's where the kernel internal linker which knows how to deal with function descriptors sits. Signed-off-by: James Bottomley Acked-by: Benjamin Herrenschmidt Acked-by: Tony Luck Acked-by: Kyle McMartin Signed-off-by: Linus Torvalds diff --git a/arch/ia64/include/asm/sections.h b/arch/ia64/include/asm/sections.h index 7286e4a..a7acad2 100644 --- a/arch/ia64/include/asm/sections.h +++ b/arch/ia64/include/asm/sections.h @@ -21,5 +21,8 @@ extern char __start_gate_brl_fsys_bubble_down_patchlist[], __end_gate_brl_fsys_b extern char __start_unwind[], __end_unwind[]; extern char __start_ivt_text[], __end_ivt_text[]; +#undef dereference_function_descriptor +void *dereference_function_descriptor(void *); + #endif /* _ASM_IA64_SECTIONS_H */ diff --git a/arch/ia64/kernel/module.c b/arch/ia64/kernel/module.c index 29aad34..545626f 100644 --- a/arch/ia64/kernel/module.c +++ b/arch/ia64/kernel/module.c @@ -31,9 +31,11 @@ #include #include #include +#include #include #include +#include #include #define ARCH_MODULE_DEBUG 0 @@ -941,3 +943,13 @@ module_arch_cleanup (struct module *mod) if (mod->arch.core_unw_table) unw_remove_unwind_table(mod->arch.core_unw_table); } + +void *dereference_function_descriptor(void *ptr) +{ + struct fdesc *desc = ptr; + void *p; + + if (!probe_kernel_address(&desc->ip, p)) + ptr = p; + return ptr; +} diff --git a/arch/parisc/kernel/module.c b/arch/parisc/kernel/module.c index fdacdd4..44138c3 100644 --- a/arch/parisc/kernel/module.c +++ b/arch/parisc/kernel/module.c @@ -47,7 +47,9 @@ #include #include #include +#include +#include #include #if 0 @@ -860,3 +862,15 @@ void module_arch_cleanup(struct module *mod) deregister_unwind_table(mod); module_bug_cleanup(mod); } + +#ifdef CONFIG_64BIT +void *dereference_function_descriptor(void *ptr) +{ + Elf64_Fdesc *desc = ptr; + void *p; + + if (!probe_kernel_address(&desc->addr, p)) + ptr = p; + return ptr; +} +#endif diff --git a/arch/powerpc/include/asm/sections.h b/arch/powerpc/include/asm/sections.h index 916018e..7710e9e 100644 --- a/arch/powerpc/include/asm/sections.h +++ b/arch/powerpc/include/asm/sections.h @@ -16,6 +16,9 @@ static inline int in_kernel_text(unsigned long addr) return 0; } +#undef dereference_function_descriptor +void *dereference_function_descriptor(void *); + #endif #endif /* __KERNEL__ */ diff --git a/arch/powerpc/kernel/module_64.c b/arch/powerpc/kernel/module_64.c index ee6a298..ad79de2 100644 --- a/arch/powerpc/kernel/module_64.c +++ b/arch/powerpc/kernel/module_64.c @@ -21,8 +21,9 @@ #include #include #include +#include #include -#include +#include #include #include #include @@ -451,3 +452,13 @@ int apply_relocate_add(Elf64_Shdr *sechdrs, return 0; } + +void *dereference_function_descriptor(void *ptr) +{ + struct ppc64_opd_entry *desc = ptr; + void *p; + + if (!probe_kernel_address(&desc->funcaddr, p)) + ptr = p; + return ptr; +} diff --git a/include/asm-generic/sections.h b/include/asm-generic/sections.h index 8feeae1..79a7ff9 100644 --- a/include/asm-generic/sections.h +++ b/include/asm-generic/sections.h @@ -14,4 +14,10 @@ extern char __kprobes_text_start[], __kprobes_text_end[]; extern char __initdata_begin[], __initdata_end[]; extern char __start_rodata[], __end_rodata[]; +/* function descriptor handling (if any). Override + * in asm/sections.h */ +#ifndef dereference_function_descriptor +#define dereference_function_descriptor(p) (p) +#endif + #endif /* _ASM_GENERIC_SECTIONS_H_ */ diff --git a/include/asm-parisc/sections.h b/include/asm-parisc/sections.h index fdd43ec..9d13c35 100644 --- a/include/asm-parisc/sections.h +++ b/include/asm-parisc/sections.h @@ -4,4 +4,9 @@ /* nothing to see, move along */ #include +#ifdef CONFIG_64BIT +#undef dereference_function_descriptor +void *dereference_function_descriptor(void *); +#endif + #endif diff --git a/lib/vsprintf.c b/lib/vsprintf.c index d8d1d11..c399bc1 100644 --- a/lib/vsprintf.c +++ b/lib/vsprintf.c @@ -27,6 +27,7 @@ #include /* for PAGE_SIZE */ #include +#include /* for dereference_function_descriptor() */ /* Works only for digits and letters, but small and fast */ #define TOLOWER(x) ((x) | 0x20) @@ -513,16 +514,6 @@ static char *string(char *buf, char *end, char *s, int field_width, int precisio return buf; } -static inline void *dereference_function_descriptor(void *ptr) -{ -#if defined(CONFIG_IA64) || defined(CONFIG_PPC64) - void *p; - if (!probe_kernel_address(ptr, p)) - ptr = p; -#endif - return ptr; -} - static char *symbol_string(char *buf, char *end, void *ptr, int field_width, int precision, int flags) { unsigned long value = (unsigned long) ptr; -- cgit v0.10.2 From d6be118a97ce51ca84035270f91c2bccecbfac5f Mon Sep 17 00:00:00 2001 From: Prarit Bhargava Date: Tue, 9 Sep 2008 09:56:08 -0400 Subject: x86: fix memmap=exactmap boot argument When using kdump modifying the e820 map is yielding strange results. For example starting with BIOS-provided physical RAM map: BIOS-e820: 0000000000000100 - 0000000000093400 (usable) BIOS-e820: 0000000000093400 - 00000000000a0000 (reserved) BIOS-e820: 0000000000100000 - 000000003fee0000 (usable) BIOS-e820: 000000003fee0000 - 000000003fef3000 (ACPI data) BIOS-e820: 000000003fef3000 - 000000003ff80000 (ACPI NVS) BIOS-e820: 000000003ff80000 - 0000000040000000 (reserved) BIOS-e820: 00000000e0000000 - 00000000f0000000 (reserved) BIOS-e820: 00000000fec00000 - 00000000fec10000 (reserved) BIOS-e820: 00000000fee00000 - 00000000fee01000 (reserved) BIOS-e820: 00000000ff000000 - 0000000100000000 (reserved) and booting with args memmap=exactmap memmap=640K@0K memmap=5228K@16384K memmap=125188K@22252K memmap=76K#1047424K memmap=564K#1047500K resulted in: user-defined physical RAM map: user: 0000000000000000 - 0000000000093400 (usable) user: 0000000000093400 - 00000000000a0000 (reserved) user: 0000000000100000 - 000000003fee0000 (usable) user: 000000003fee0000 - 000000003fef3000 (ACPI data) user: 000000003fef3000 - 000000003ff80000 (ACPI NVS) user: 000000003ff80000 - 0000000040000000 (reserved) user: 00000000e0000000 - 00000000f0000000 (reserved) user: 00000000fec00000 - 00000000fec10000 (reserved) user: 00000000fee00000 - 00000000fee01000 (reserved) user: 00000000ff000000 - 0000000100000000 (reserved) But should have resulted in: user-defined physical RAM map: user: 0000000000000000 - 00000000000a0000 (usable) user: 0000000001000000 - 000000000151b000 (usable) user: 00000000015bb000 - 0000000008ffc000 (usable) user: 000000003fee0000 - 000000003ff80000 (ACPI data) This is happening because of an improper usage of strcmp() in the e820 parsing code. The strcmp() always returns !0 and never resets the value for e820.nr_map and returns an incorrect user-defined map. This patch fixes the problem. Signed-off-by: Prarit Bhargava Signed-off-by: Ingo Molnar diff --git a/arch/x86/kernel/e820.c b/arch/x86/kernel/e820.c index 9af8907..66e48aa 100644 --- a/arch/x86/kernel/e820.c +++ b/arch/x86/kernel/e820.c @@ -1203,7 +1203,7 @@ static int __init parse_memmap_opt(char *p) if (!p) return -EINVAL; - if (!strcmp(p, "exactmap")) { + if (!strncmp(p, "exactmap", 8)) { #ifdef CONFIG_CRASH_DUMP /* * If we are doing a crash dump, we still need to know -- cgit v0.10.2 From 61c22c34c6f80a8e89cff5ff717627c54cc14fd4 Mon Sep 17 00:00:00 2001 From: Thomas Gleixner Date: Tue, 9 Sep 2008 21:38:57 +0200 Subject: clockevents: remove WARN_ON which was used to gather information The issue of the endless reprogramming loop due to a too small min_delta_ns was fixed with the previous updates of the clock events code, but we had no information about the spread of this problem. I added a WARN_ON to get automated information via kerneloops.org and to get some direct reports, which allowed me to analyse the affected machines. The WARN_ON has served its purpose and would be annoying for a release kernel. Remove it and just keep the information about the increase of the min_delta_ns value. Signed-off-by: Thomas Gleixner diff --git a/kernel/time/tick-oneshot.c b/kernel/time/tick-oneshot.c index 2e35501..2e8de67 100644 --- a/kernel/time/tick-oneshot.c +++ b/kernel/time/tick-oneshot.c @@ -43,19 +43,17 @@ int tick_dev_program_event(struct clock_event_device *dev, ktime_t expires, * and emit a warning. */ if (++i > 2) { - printk(KERN_WARNING "CE: __tick_program_event of %s is " - "stuck %llx %llx\n", dev->name ? dev->name : "?", - now.tv64, expires.tv64); - printk(KERN_WARNING - "CE: increasing min_delta_ns %ld to %ld nsec\n", - dev->min_delta_ns, dev->min_delta_ns << 1); - WARN_ON(1); - - /* Double the min. delta and try again */ + /* Increase the min. delta and try again */ if (!dev->min_delta_ns) dev->min_delta_ns = 5000; else - dev->min_delta_ns <<= 1; + dev->min_delta_ns += dev->min_delta_ns >> 1; + + printk(KERN_WARNING + "CE: %s increasing min_delta_ns to %lu nsec\n", + dev->name ? dev->name : "?", + dev->min_delta_ns << 1); + i = 0; } -- cgit v0.10.2 From e550dfb0c2c31b6363aa463a035fc9f8dcaa3c9b Mon Sep 17 00:00:00 2001 From: Neil Horman Date: Tue, 9 Sep 2008 13:51:35 -0700 Subject: ipv6: Fix OOPS in ip6_dst_lookup_tail(). This fixes kernel bugzilla 11469: "TUN with 1024 neighbours: ip6_dst_lookup_tail NULL crash" dst->neighbour is not necessarily hooked up at this point in the processing path, so blindly dereferencing it is the wrong thing to do. This NULL check exists in other similar paths and this case was just an oversight. Also fix the completely wrong and confusing indentation here while we're at it. Based upon a patch by Evgeniy Polyakov. Signed-off-by: Neil Horman Signed-off-by: David S. Miller diff --git a/net/ipv6/ip6_output.c b/net/ipv6/ip6_output.c index 0e844c2..3df2c44 100644 --- a/net/ipv6/ip6_output.c +++ b/net/ipv6/ip6_output.c @@ -943,39 +943,39 @@ static int ip6_dst_lookup_tail(struct sock *sk, } #ifdef CONFIG_IPV6_OPTIMISTIC_DAD - /* - * Here if the dst entry we've looked up - * has a neighbour entry that is in the INCOMPLETE - * state and the src address from the flow is - * marked as OPTIMISTIC, we release the found - * dst entry and replace it instead with the - * dst entry of the nexthop router - */ - if (!((*dst)->neighbour->nud_state & NUD_VALID)) { - struct inet6_ifaddr *ifp; - struct flowi fl_gw; - int redirect; - - ifp = ipv6_get_ifaddr(net, &fl->fl6_src, - (*dst)->dev, 1); - - redirect = (ifp && ifp->flags & IFA_F_OPTIMISTIC); - if (ifp) - in6_ifa_put(ifp); - - if (redirect) { - /* - * We need to get the dst entry for the - * default router instead - */ - dst_release(*dst); - memcpy(&fl_gw, fl, sizeof(struct flowi)); - memset(&fl_gw.fl6_dst, 0, sizeof(struct in6_addr)); - *dst = ip6_route_output(net, sk, &fl_gw); - if ((err = (*dst)->error)) - goto out_err_release; - } + /* + * Here if the dst entry we've looked up + * has a neighbour entry that is in the INCOMPLETE + * state and the src address from the flow is + * marked as OPTIMISTIC, we release the found + * dst entry and replace it instead with the + * dst entry of the nexthop router + */ + if ((*dst)->neighbour && !((*dst)->neighbour->nud_state & NUD_VALID)) { + struct inet6_ifaddr *ifp; + struct flowi fl_gw; + int redirect; + + ifp = ipv6_get_ifaddr(net, &fl->fl6_src, + (*dst)->dev, 1); + + redirect = (ifp && ifp->flags & IFA_F_OPTIMISTIC); + if (ifp) + in6_ifa_put(ifp); + + if (redirect) { + /* + * We need to get the dst entry for the + * default router instead + */ + dst_release(*dst); + memcpy(&fl_gw, fl, sizeof(struct flowi)); + memset(&fl_gw.fl6_dst, 0, sizeof(struct in6_addr)); + *dst = ip6_route_output(net, sk, &fl_gw); + if ((err = (*dst)->error)) + goto out_err_release; } + } #endif return 0; -- cgit v0.10.2 From adee14b2e1557d0a8559f29681732d05a89dfc35 Mon Sep 17 00:00:00 2001 From: Linus Torvalds Date: Tue, 9 Sep 2008 16:27:49 -0700 Subject: Linux 2.6.27-rc6 diff --git a/Makefile b/Makefile index f448e00..4ff83ea 100644 --- a/Makefile +++ b/Makefile @@ -1,7 +1,7 @@ VERSION = 2 PATCHLEVEL = 6 SUBLEVEL = 27 -EXTRAVERSION = -rc5 +EXTRAVERSION = -rc6 NAME = Rotary Wombat # *DOCUMENTATION* -- cgit v0.10.2